@y20070316
2017-02-17T00:59:36.000000Z
字数 7813
阅读 1043
OI 校内赛
给定,。
求,其中
假如存在某个变换,使得。我们快速的进行变换和逆变换,则可以快速求解答案。
这里介绍莫比乌斯变换:
变换:给定,求
考虑dp,设表示对于集合,前位可以任意改动的所有子集的和。
奠基:
void Trans(int *f,int n) {for (int i=1;i<(1<<n);i<<=1)for (int j=0;j<(1<<n);j++)if (j&i)f[j]+=f[j^i];}
逆变换:给定,求。
怎么变换过去的,就怎么变换回来。
直接和上面的代码相反就好了。
#include <cstdio>#include <cctype>#define F(i,a,b) for (int i=(a);i<=(b);i++)#define LL unsigned intLL rd(void);const int N=1048576;int n,nk;LL f[N];LL g[N];LL h[N];LL ans;int main(void) {#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifn=rd();nk=(1<<n);F(i,0,nk-1)f[i]=rd();F(i,0,nk-1)g[i]=rd();for (int j=1;j<nk;j<<=1)F(i,0,nk-1) if (i&j) {f[i]+=f[i^j];g[i]+=g[i^j];}F(i,0,nk-1)h[i]=f[i]*g[i];for (int j=1;j<nk;j<<=1)F(i,0,nk-1) if (i&j)h[i]-=h[i^j];F(i,0,nk-1)ans+=h[i]*(i+1);printf("%u\n",ans);return 0;}LL rd(void) {LL x=0,f=1; char c=getchar();while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();}while (isdigit(c)) {x=x*10+c-'0';c=getchar();}return x*f;}
#include <cstdio>#include <cctype>#define F(i,a,b) for (int i=(a);i<=(b);i++)#define LL unsigned intLL rd(void);const int N=32;const int S=1048576;int n,nk;LL f[S];LL g[S];LL h[S];LL ans;void FWT(LL *a,int nk) {for (int i=2;i<=nk;i<<=1)for (int j=0;j<nk;j+=i)F(k,0,i/2-1) {LL x=a[j+k];LL y=a[j+k+i/2];a[j+k]=x;a[j+k+i/2]=x+y;}}void DWT(LL *a,int nk) {for (int i=2;i<=nk;i<<=1)for (int j=0;j<nk;j+=i)F(k,0,i/2-1) {LL x=a[j+k];LL y=a[j+k+i/2];a[j+k]=x;a[j+k+i/2]=y-x;}}int main(void) {#ifndef ONLINE_JUDGEfreopen("A.in","r",stdin);freopen("A.out","w",stdout);#endifn=rd();nk=(1<<n);F(i,0,nk-1)f[i]=rd();F(i,0,nk-1)g[i]=rd();FWT(f,nk);FWT(g,nk);F(i,0,nk-1)h[i]=f[i]*g[i];DWT(h,nk);F(i,0,nk-1)ans+=h[i]*(i+1);printf("%u\n",ans);return 0;}LL rd(void) {LL x=0,f=1; char c=getchar();while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();}while (isdigit(c)) {x=x*10+c-'0';c=getchar();}return x*f;}
注意到,最终答案的情形必然是这样的:我们过两个点作一条直线,一个人巡查直线左边的所有点,一个人巡查右边的所有点,对应左边有面积,右边有面积,求凸包,通过分割成三角形的方法计算多边形面积。
#include <cstdio>#include <cctype>#include <cmath>#include <algorithm>using namespace std;#define F(i,a,b) for (int i=(a);i<=(b);i++)#define D(i,a,b) for (int i=(a);i>=(b);i--)#define LD long doubleint rd(void);const int N=64;const LD MAX=1e30;int n;struct point {LD x,y;point(LD _x=0,LD _y=0) {x=_x,y=_y;}friend point operator - (point a,point b) {return point(a.x-b.x,a.y-b.y);}friend LD operator * (point a,point b) {return a.x*b.x+a.y*b.y;}friend LD operator ^ (point a,point b) {return a.x*b.y-a.y*b.x;}friend int operator < (point a,point b) {if (a.x!=b.x)return a.x<b.x;else return a.y<b.y;}void Read(void) {x=(LD)rd();y=(LD)rd();}}p[N];point stk[N]; int top;point q1[N]; int len1;point q2[N]; int len2;point c[N]; int tc;LD ans;void Polygon(point *p,int n) {//n>=1sort(p+1,p+n+1);while (len1>0)q1[len1--]=point();F(i,1,n) {while (len1>=2) {if (((q1[len1]-q1[len1-1])^(p[i]-q1[len1-1]))<=0)q1[len1--]=point();else break;}q1[++len1]=p[i];}while (len2>0)q2[len2--]=point();D(i,n,1) {while (len2>=2) {if (((q2[len2]-q2[len2-1])^(p[i]-q2[len2-1]))<=0)q2[len2--]=point();else break;}q2[++len2]=p[i];}while (top>0)stk[top--]=point();F(i,1,len1)stk[++top]=q1[i];F(i,2,len2-1)stk[++top]=q2[i];}LD dis(point a,point b) {return sqrt((a-b)*(a-b));}LD get(point a,point b,point c) {LD x=dis(a,b);LD y=dis(b,c);LD z=dis(c,a);LD p=(x+y+z)/2;return sqrt(p*(p-x)*(p-y)*(p-z));}LD Calc(void) {if (top<=2)return 0;LD sum=0;F(i,2,top-1) {LD t=get(stk[1],stk[i],stk[i+1]);sum+=t;}return sum;}void Split(point s,point t,int kd) {/*kd=0:左边,包括两点及线上的点kd=1:右边*/while (tc>0)c[tc--]=point();F(i,1,n)if (kd==(((t-s)^(p[i]-s))<0))c[++tc]=p[i];}int main(void) {#ifndef ONLINE_JUDGEfreopen("B.in","r",stdin);freopen("B.out","w",stdout);#endifn=rd();F(i,1,n)p[i].Read();ans=MAX;F(i,1,n)F(j,1,n) {Split(p[i],p[j],0);Polygon(c,tc);LD t=Calc();Split(p[i],p[j],1);Polygon(c,tc);t=max(t,Calc());ans=min(ans,t);}printf("%0.6Lf\n",ans);return 0;}int rd(void) {int x=0,f=1; char c=getchar();while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();}while (isdigit(c)) {x=x*10+c-'0';c=getchar();}return x*f;}
#include <cstdio>#include <cctype>#include <algorithm>#include <vector>using namespace std;#define F(i,a,b) for (int i=(a);i<=(b);i++)#define fore(v,x) for (vector<int>::iterator v=g[x].begin();v!=g[x].end();v++)#define LL long longint rd(void);char rdc(void);int trans(int u,LL ans,int n);int trans_w(int u,LL ans,int tot);const int N=131072;const int M=20000000;int n,m;vector<int> g[N];int pre[N],siz[N],son[N],dep[N];int dfn[N],ind,top[N];int tot;int rt[N],tms,now_rt;struct Tree {int lc,rc;int cnt;LL add,del;//cnt表示区间公差,第一项为0LL sum;}tr[M];void Find(int x) {siz[x]=1;fore(v,x)if (pre[x]!=*v) {pre[*v]=x;dep[*v]=dep[x]+1;Find(*v);siz[x]+=siz[*v];if (siz[son[x]]<siz[*v])son[x]=*v;}}void Split(int x,int anc) {dfn[x]=++ind;top[x]=anc;if (son[x]>0)Split(son[x],anc);fore(v,x)if (*v!=pre[x]&&*v!=son[x])Split(*v,*v);}int LCA(int x,int y) {while (top[x]!=top[y]) {if (dep[top[x]]<dep[top[y]])swap(x,y);x=pre[top[x]];}return dep[x]<dep[y]?x:y;}void Update(int x) {int lc=tr[x].lc,rc=tr[x].rc;tr[x].cnt=tr[lc].cnt+tr[rc].cnt;tr[x].sum=tr[lc].sum+tr[rc].sum;tr[x].sum+=tr[x].add*tr[x].cnt;tr[x].sum+=tr[x].del*(tr[x].cnt-1)*tr[x].cnt>>1;}int Build(int l,int r) {int x=++tot;tr[x].cnt=r-l+1;if (l!=r) {int mid=(l+r)>>1;tr[x].lc=Build(l,mid);tr[x].rc=Build(mid+1,r);}return x;}int Copynode(int frm) {int x=++tot;tr[x]=tr[frm];return x;}int Change(int frm,int l,int r,int ql,int qr,LL a,LL b) {if (ql>r||qr<l)return frm;int x=Copynode(frm);if (ql<=l&&r<=qr) {tr[x].add+=a+b*(l-ql);tr[x].del+=b;tr[x].sum+=(a+b*(l-ql))*tr[x].cnt;tr[x].sum+=b*(tr[x].cnt-1)*tr[x].cnt>>1;return x;}int mid=(l+r)>>1;tr[x].lc=Change(tr[frm].lc,l,mid,ql,qr,a,b);tr[x].rc=Change(tr[frm].rc,mid+1,r,ql,qr,a,b);Update(x);return x;}LL Query(int x,int l,int r,int ql,int qr) {if (ql>r||qr<l)return 0;if (ql<=l&&r<=qr)return tr[x].sum;int mid=(l+r)>>1;int aL=max(l,ql);int aR=min(r,qr);int cnt=aR-aL+1;LL ans=tr[x].add*cnt+(tr[x].del*(aL-l+aR-l)*cnt>>1);ans+=Query(tr[x].lc,l,mid,ql,qr);ans+=Query(tr[x].rc,mid+1,r,ql,qr);return ans;}void Change_Path(int u,int v,int a,int b) {int anc=LCA(u,v);int tu=u,tv=v;while (top[u]!=top[anc]) {int dis=dep[tu]-dep[top[u]];now_rt=Change(now_rt,1,n,dfn[top[u]],dfn[u],a+b*dis,-b);u=pre[top[u]];}while (top[v]!=top[anc]) {int dis=dep[tu]+dep[top[v]]-dep[anc]-dep[anc];now_rt=Change(now_rt,1,n,dfn[top[v]],dfn[v],a+b*dis,b);v=pre[top[v]];}if (u==anc) {int dis=dep[tu]-dep[anc];now_rt=Change(now_rt,1,n,dfn[u],dfn[v],a+b*dis,b);}else {int dis=dep[tu]-dep[anc];now_rt=Change(now_rt,1,n,dfn[v],dfn[u],a+b*dis,-b);}rt[++tms]=now_rt;}LL Query_Path(int u,int v) {int anc=LCA(u,v);LL sum=0;while (top[u]!=top[anc]) {sum+=Query(now_rt,1,n,dfn[top[u]],dfn[u]);u=pre[top[u]];}while (top[v]!=top[anc]) {sum+=Query(now_rt,1,n,dfn[top[v]],dfn[v]);v=pre[top[v]];}if (u==anc)sum+=Query(now_rt,1,n,dfn[u],dfn[v]);else sum+=Query(now_rt,1,n,dfn[v],dfn[u]);return sum;}void Roll(int w) {now_rt=rt[w];}int main(void) {#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifn=rd(),m=rd();F(i,1,n-1) {int u=rd(),v=rd();g[u].push_back(v);g[v].push_back(u);}Find(1);Split(1,1);now_rt=rt[0]=Build(1,n);LL ans=0;F(i,1,m) {char c=rdc();if (c=='c') {int u=rd(),v=rd(),a=rd(),b=rd();u=trans(u,ans,n);v=trans(v,ans,n);Change_Path(u,v,a,b);}else if (c=='q') {int u=rd(),v=rd();u=trans(u,ans,n);v=trans(v,ans,n);ans=Query_Path(u,v);printf("%lld\n",ans);}else if (c=='r') {int w=rd();w=trans_w(w,ans,tms);Roll(w);}}return 0;}int rd(void) {int x=0,f=1; char c=getchar();while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();}while (isdigit(c)) {x=x*10+c-'0';c=getchar();}return x*f;}char rdc(void) {char c=getchar();while (!isalpha(c))c=getchar();return c;}int trans(int u,LL ans,int n) {return (u+ans)%n+1;}int trans_w(int w,LL ans,int tot) {return (w+ans)%(tot+1);}