problems
http://gdoi.sysu.edu.cn/wp-content/uploads/2015/03/GDKOI-2015-day1.pdf
http://gdoi.sysu.edu.cn/wp-content/uploads/2015/03/GDKOI-2015-day21.pdf
necklace
回文串问题。
把字符串复制一遍,使得环状变成线状。
然后就是问最长回文串,直接套用manacher算法。
wordcount
网络流问题。
把每个格点(i,j)在网络流中拆分成两个点,这两个点之间连一条流量为cnt[i][j]的边,其中左边的称为入点,右边的称为出点。
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int dblcmp(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} inline void SetOpen(string s) { freopen((s+".in").c_str(),"r",stdin); freopen((s+".out").c_str(),"w",stdout); } inline int Getin_Int() { int res=0,flag=1;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){flag=-flag;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return res*flag; } inline LL Getin_LL() { LL res=0,flag=1;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){flag=-flag;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return res*flag; } const int maxN=10000; int N; vector<int> edge[maxN/2+100],ans; inline int DFS(int x) { int now=x; x%=N/2; while(!edge[x].empty()) { int y=edge[x].back(); edge[x].pop_back(); DFS(y); } ans.push_back(now); } int main() { SetOpen("circle"); int i; N=Getin_Int(); if(N&1){puts("-1\n");return 0;} re(i,0,N/2-1){edge[i].push_back(2*i);edge[i].push_back(2*i+1);} DFS(0); red(i,ans.size()-1,0)printf("%d ",ans[i]);printf("\n"); return 0; }
Ask u v c:先求出lca,然后在第c棵中查询:u到根节点的路径中颜色为c的点的权值和+u到根节点的路径中颜色为c的点的权值和-lca到根节点的路径中颜色为c的权值和-lca的父亲到根节点的路径中颜色为c的权值和
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int dblcmp(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} inline void SetOpen(string s) { freopen((s+".in").c_str(),"r",stdin); freopen((s+".out").c_str(),"w",stdout); } inline int Getin_Int() { int res=0,flag=1;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){flag=-flag;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return res*flag; } inline LL Getin_LL() { LL res=0,flag=1;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){flag=-flag;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return res*flag; } const int maxN=50000; const int maxM=50000; const int maxC=10; int N,M,C; int c[maxN+100],v[maxN+100]; int first[maxN+100],now; struct Tedge{int v,next;}edge[2*maxN+100]; int fa[maxN+100],dep[maxN+100]; int jump[maxN+100][30]; int sum[maxN+100][maxC+3]; int id[maxN+100],l[maxN+100],r[maxN+100],cnt; inline void addedge(int u,int v) { now++; edge[now].v=v; edge[now].next=first[u]; first[u]=now; } int que[maxN+100],head,tail; inline void BFS(int S) { mmst(fa,-1); que[head=tail=0]=S; fa[S]=0; dep[S]=1; while(head<=tail) { int u=que[head++],i,v; for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(v!=fa[u]) { que[++tail]=v; fa[v]=u; dep[v]=dep[u]+1; } } } int sta[maxN+100],top; int last[maxN+100]; inline void DFS(int S) { int j; re(j,1,N)last[j]=first[j]; sta[top=1]=S; id[S]=cnt=1; while(top>=1) { int u=sta[top],&i=last[u],v; for(v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(!id[v]) { id[v]=++cnt; sta[++top]=v; break; } if(i==-1)top--; } } inline void swim(int &x,int H) { int i; for(i=0;H!=0;H/=2,i++)if(H&1)x=jump[x][i]; } inline int Ask_LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); swim(x,dep[x]-dep[y]); if(x==y)return x; int i; red(i,30-1,0)if(jump[x][i]!=jump[y][i]){x=jump[x][i];y=jump[y][i];} return jump[x][0]; } struct Ttree { Ttree *l,*r; int add,v; }*tree[maxC+10]; inline Ttree *NewTtree() { Ttree *res=new Ttree; res->l=res->r=0; res->add=res->v=0; return res; } inline void down(Ttree *&root,int l,int r,int mid) { if(root->add==0)return; int add=root->add;root->add=0; if(l==r)return; if(!root->l)root->l=NewTtree(); if(l==mid) root->l->v+=add; root->l->add+=add; if(!root->r)root->r=NewTtree(); if(mid+1==r) root->r->v+=add; root->r->add+=add; } inline void update(Ttree *&root,int l,int r,int x,int y,int v) { if(!root) root=NewTtree(); if(l>r || y<l || r<x)return; int mid=(l+r)/2; down(root,l,r,mid); if(x<=l && r<=y) { if(l==r)root->v+=v; root->add+=v; return; } update(root->l,l,mid,x,y,v); update(root->r,mid+1,r,x,y,v); } inline void change(Ttree *&R1,Ttree *&R2,int l,int r,int x,int y,int temp1,int temp2) { if(!R1) R1=NewTtree(); if(!R2) R2=NewTtree(); if(l>r || y<l || r<x) return; int mid=(l+r)/2; down(R1,l,r,mid); down(R2,l,r,mid); if(x<=l && r<=y) { if(l==r)R1->v+=-temp1+temp2;R1->add+=-temp1+temp2; if(l==r)R2->v+=-temp2+temp1;R2->add+=-temp2+temp1; swap(R1,R2); return; } change(R1->l,R2->l,l,mid,x,y,temp1,temp2); change(R1->r,R2->r,mid+1,r,x,y,temp1,temp2); } inline int ask(Ttree *&root,int l,int r,int x) { if(!root) root=NewTtree(); if(l>r || x<l || r<x)return 0; int mid=(l+r)/2; down(root,l,r,mid); if(x<=l && r<=x)return root->v; if(x<=mid) return ask(root->l,l,mid,x); else return ask(root->r,mid+1,r,x); } int main() { SetOpen("tree"); int i,j; N=Getin_Int();C=0; re(i,1,N){c[i]=Getin_Int()+1;upmax(C,c[i]);} re(i,1,N)v[i]=Getin_Int(); mmst(first,-1);now=-1; re(i,1,N-1) { int x=Getin_Int()+1,y=Getin_Int()+1; addedge(x,y); addedge(y,x); } BFS(1); re(i,0,tail) { int u=que[i]; jump[u][0]=fa[u]; re(j,1,30-1)jump[u][j]=jump[jump[u][j-1]][j-1]; } re(i,0,tail) { int u=que[i]; re(j,1,C)sum[u][j]=sum[fa[u]][j]; sum[u][c[u]]+=v[u]; } DFS(1); red(j,tail,0) { int u=que[j],v; l[u]=r[u]=id[u]; for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)if(v!=fa[u]) { upmin(l[u],l[v]); upmax(r[u],r[v]); } } re(i,1,N)re(j,1,C)update(tree[j],1,N,id[i],id[i],sum[i][j]); M=Getin_Int(); while(M--) { char S[20]; int a,b,x,y,c,val,lca,temp1,temp2,temp3; scanf("%s",S); switch(S[0]) { case 'C': a=Getin_Int()+1;x=Getin_Int()+1;y=Getin_Int()+1; temp1=ask(tree[x],1,N,id[fa[a]]); temp2=ask(tree[y],1,N,id[fa[a]]); change(tree[x],tree[y],1,N,l[a],r[a],temp1,temp2); break; case 'A': a=Getin_Int()+1;b=Getin_Int()+1;c=Getin_Int()+1; lca=Ask_LCA(a,b); printf("%d\n",ask(tree[c],1,N,id[a])+ask(tree[c],1,N,id[b])-ask(tree[c],1,N,id[lca])-ask(tree[c],1,N,id[fa[lca]])); break; case 'S': a=Getin_Int()+1;c=Getin_Int()+1;val=Getin_Int(); re(i,1,C) { temp1=ask(tree[i],1,N,id[a])-ask(tree[i],1,N,id[fa[a]]); if(temp1==0) continue; update(tree[i],1,N,l[a],r[a],-temp1); break; } update(tree[c],1,N,l[a],r[a],val); break; } } return 0; }
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int dblcmp(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} inline void SetOpen(string s) { freopen((s+".in").c_str(),"r",stdin); freopen((s+".out").c_str(),"w",stdout); } inline int Getin_Int() { int res=0,flag=1;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){flag=-flag;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return res*flag; } inline LL Getin_LL() { LL res=0,flag=1;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){flag=-flag;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return res*flag; } const int maxN=200; const int maxK=maxN/2; int N,K; struct Tdata { int x,y,z; inline void input(){x=Getin_Int();y=Getin_Int();z=Getin_Int();} }data[maxN+10]; int F[maxN+10][maxK+10]; int ans; inline bool cmpy(Tdata a,Tdata b){return a.y>b.y;} int main() { SetOpen("planetcup"); int i,j,k; N=Getin_Int();K=Getin_Int(); re(i,1,N)data[i].input(); sort(data+1,data+N+1,cmpy); ans=0; re(k,1,N) { int p=data[k].x,cnt=0; mmst(F,-1); F[0][0]=0; re(i,0,N-1) { if(data[i+1].z==0 && data[i+1].x<p) { re(j,0,K)F[i+1][j]=F[i][j]; continue; } re(j,0,K) { if(F[i][j]==-1)continue; if(data[i+1].z==1 && data[i+1].x<p) { if(cnt-j+1<=K) upmax(F[i+1][j],F[i][j]+data[i+1].y); else upmax(F[i+1][j],F[i][j]); continue; } if(data[i+1].x>=p && j+1<=K) upmax(F[i+1][j+1],F[i][j]+data[i+1].x*data[i+1].z); if(cnt-j+1<=K) upmax(F[i+1][j],F[i][j]+data[i+1].y*data[i+1].z); else upmax(F[i+1][j],F[i][j]); } cnt++; } upmax(ans,F[N][K]); } cout<<ans<<endl; return 0; }
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int dblcmp(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} inline void SetOpen(string s) { freopen((s+".in").c_str(),"r",stdin); freopen((s+".out").c_str(),"w",stdout); } inline int Getin_Int() { int res=0,flag=1;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){flag=-flag;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return res*flag; } inline LL Getin_LL() { LL res=0,flag=1;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){flag=-flag;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return res*flag; } const int maxN=100000; int N,Q; int first[maxN+100],now; struct Tedge{int v,next;}edge[2*maxN+100]; int fa[maxN+100],dep[maxN+100]; int jump[maxN+100][50]; int p[maxN+100][4];//0上升 1下降 2先上后下 3先下后上 int t[maxN+100][50]; int ans; inline void addedge(int u,int v) { now++; edge[now].v=v; edge[now].next=first[u]; first[u]=now; } int que[maxN+100],head,tail; inline void BFS(int S) { dep[que[head=tail=0]=S]=1; while(head<=tail) { int u=que[head++],i,v; for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)dep[que[++tail]=v]=dep[u]+1; } } inline int swim(int x,int H) { for(int i=0;H!=0;H/=2,i++)if(H&1)x=jump[x][i]; return x; } inline int Ask_LCA(int x,int y) { if(dep[x]<dep[y]) swap(x,y); x=swim(x,dep[x]-dep[y]); if(x==y)return x; int i; red(i,30,0)if(jump[x][i]!=jump[y][i]){x=jump[x][i];y=jump[y][i];} return jump[x][0]; } inline int up(int x,int y,int f) { return min(p[x][f],dep[x]-dep[y]+1); } inline int down(int x,int y,int f) { int l=0,r=dep[x]-dep[y],mid; while(l<=r) { mid=(l+r)/2; int temp=swim(x,mid); if(p[temp][f]>=dep[temp]-dep[y]+1) r=mid-1; else l=mid+1; } return dep[swim(x,l)]-dep[y]+1; } inline int solve(int a,int b) { int i,res=0,H=dep[a]-dep[b]+1,x=a,y; for(i=0;H!=0;H/=2,i++)if(H&1) { y=swim(x,(1<<i)-1); upmax(res,t[x][i]); if(a!=x) { upmax(res,down(a,x,0)+up(x,y,2)-1); upmax(res,down(a,x,1)+up(x,y,3)-1); upmax(res,down(a,x,2)+up(x,y,1)-1); upmax(res,down(a,x,3)+up(x,y,0)-1); } x=fa[y]; } return res; } int main() { SetOpen("v"); int i,j; N=Getin_Int(); mmst(first,-1);now=-1; re(i,2,N){fa[i]=Getin_Int();addedge(fa[i],i);} BFS(1); re(i,0,30)jump[1][i]=1; re(j,1,tail) { int u=que[j]; jump[u][0]=fa[u]; re(i,1,30)jump[u][i]=jump[jump[u][i-1]][i-1]; } re(j,0,tail) { int u=que[j]; if(u<fa[u])p[u][0]=p[fa[u]][0]+1; else p[u][0]=1; if(u>fa[u])p[u][1]=p[fa[u]][1]+1; else p[u][1]=1; p[u][2]=p[u][1];if(u<fa[u])p[u][2]=max(p[fa[u]][2],p[fa[u]][1])+1; p[u][3]=p[u][0];if(u>fa[u])p[u][3]=max(p[fa[u]][3],p[fa[u]][0])+1; } re(j,0,tail) { int a=que[j],c,d; t[a][0]=1; re(i,1,30) { c=jump[a][i-1]; d=swim(c,dep[a]-dep[c]-1); t[a][i]=max(t[a][i-1],t[c][i-1]); upmax(t[a][i],down(a,c,0)+up(c,d,2)-1); upmax(t[a][i],down(a,c,1)+up(c,d,3)-1); upmax(t[a][i],down(a,c,2)+up(c,d,1)-1); upmax(t[a][i],down(a,c,3)+up(c,d,0)-1); } } ans=0; Q=Getin_Int(); while(Q--) { int u=Getin_Int()^ans,v=Getin_Int()^ans,lca; ans=0; lca=Ask_LCA(u,v); upmax(ans,solve(u,lca)); upmax(ans,solve(v,lca)); upmax(ans,down(u,lca,0)+down(v,lca,2)-1); upmax(ans,down(u,lca,1)+down(v,lca,3)-1); upmax(ans,down(u,lca,2)+down(v,lca,0)-1); upmax(ans,down(u,lca,3)+down(v,lca,1)-1); printf("%d\n",ans); } return 0; }