bzoj 3052: [wc2013]糖果公园 带修改莫队
3052: [wc2013]糖果公园
Time Limit: 250 Sec Memory Limit: 512 MBSubmit: 506 Solved: 189
[Submit][Status]
Description
Input
Output
Sample Input
Sample Input
Sample Output
84
131
27
84
131
27
84
HINT
本来这道题想到了莫队算法,但是看到带修改就直接放弃了。结果看题解才发现带修改居然也能用莫队!!!之所以可以这样用,是因为修改的时间复杂度非常非常低,以至于可以在修改的时间轴上任意跳跃。具体细节自己去看其他题解啦。
写的有点长,但是跑的还算比较快。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define MAXN 100100 #define MAXB 2200 #define MAXQ 100100 #define MAXV MAXN #define MAXE MAXV*2 typedef long long qword; inline int nextInt() { register int x=0; register int ch; while (ch=getchar(),ch<'0' || ch>'9'); while (x=x*10+ch-'0',ch=getchar(),ch<='9' && ch>='0'); return x; } int n,m,q,sb; struct Edge { int np; Edge *next; }E[MAXE],*V[MAXV]; int tope=-1; int que[MAXN]; void addedge(int x,int y) { E[++tope].np=y; E[tope].next=V[x]; V[x]=&E[tope]; } int depth[MAXN]; int pnt[MAXN]; int top[MAXN],bsiz[MAXN]; int belong[MAXN]; int topb=0; void bfs1() { Edge *ne; int now; int head=-1,tail=0; que[0]=1; pnt[1]=1; belong[1]=++topb; top[1]=1; bsiz[1]=1; depth[1]=1; while (head<tail) { now=que[++head]; for (ne=V[now];ne;ne=ne->next) { if (ne->np==pnt[now])continue; que[++tail]=ne->np; pnt[ne->np]=now; depth[ne->np]=depth[now]+1; if (bsiz[belong[now]]<sb) { bsiz[belong[now]]++; belong[ne->np]=belong[now]; top[ne->np]=top[now]; }else { belong[ne->np]=++topb; bsiz[topb]=1; top[ne->np]=ne->np; } } } } int jump[20][MAXN]; void init_lca() { for (int i=1;i<=n;i++) jump[0][i]=pnt[i]; for (int j=1;j<20;j++) for (int i=1;i<=n;i++) jump[j][i]=jump[j-1][jump[j-1][i]]; } int lca(int x,int y) { if (depth[x]<depth[y])swap(x,y); int dep=depth[x]-depth[y]; for (int i=0;i<20;i++) if (dep & (1<<i)) x=jump[i][x]; if (x==y)return x; for (int i=19;i>=0;i--) if (jump[i][x]!=jump[i][y]) x=jump[i][x],y=jump[i][y]; return pnt[x]; } int get_dis(int x,int y) { return depth[x]+depth[y]-2*depth[lca(x,y)]; } struct qur_t { int s,t,id; int upper_pos; qword ans; }qur[MAXQ]; int topq=-1; bool cmp_qur_block(qur_t a1,qur_t a2) { if (belong[a1.s]!=belong[a2.s]) return belong[a1.s]<belong[a2.s]; if (belong[a1.t]!=belong[a2.t]) return belong[a1.t]<belong[a2.t]; return a1.id<a2.id; } bool cmp_qur_id(qur_t a1,qur_t a2) { return a1.id<a2.id; } int sweet[MAXN]; qword suprise[MAXN]; int candy[MAXN]; struct mdfy_t { int pos,cnew,cold,id; }mdfy[MAXN]; int topm=-1; struct path { int s,t,a,ds; path(int s,int t):s(s),t(t) { a=lca(s,t); ds=depth[s]+depth[t]-2*depth[a]; } path(){} bool inside(int x) { return get_dis(x,s)+get_dis(x,t)==ds; } void get_path(int *step,int &tops) { tops=-1; for (int x=s;x!=a;x=pnt[x]) step[++tops]=x; tops=ds; for (int x=t;x!=a;x=pnt[x]) step[tops--]=x; step[tops--]=a; tops=ds; } }; int tot[MAXN]; bool inside[MAXN]; int step[MAXN],tops; int main() { // freopen("input.txt","r",stdin); // freopen("output.txt","w",stdout); int x,y,z; n=nextInt(),m=nextInt(),q=nextInt(); sb=pow(n,2.0/3); for (int i=1;i<=m;i++) sweet[i]=nextInt(); for (int i=1;i<=n;i++) suprise[i]=nextInt(); for (int i=1;i<=n;i++)suprise[i]+=suprise[i-1]; for (int i=1;i<n;i++) { x=nextInt(),y=nextInt(); addedge(x,y); addedge(y,x); } for (int i=1;i<=n;i++) candy[i]=nextInt(); int opt; for (int i=1;i<=q;i++) { opt=nextInt(); if (opt==0) { x=nextInt(),y=nextInt(); ++topm; mdfy[topm].pos=x; mdfy[topm].cnew=y; mdfy[topm].cold=candy[x]; candy[x]=y; mdfy[topm].id=i; }else { x=nextInt(),y=nextInt(); ++topq; qur[topq].s=x; qur[topq].t=y; qur[topq].upper_pos=topm+1; qur[topq].id=i; } } for (int i=topm;i>=0;i--) candy[mdfy[i].pos]=mdfy[i].cold; bfs1(); init_lca(); sort(qur,qur+topq+1,cmp_qur_block); for (int i=0;i<qur[0].upper_pos;i++) candy[mdfy[i].pos]=mdfy[i].cnew; int a; a=lca(qur[0].s,qur[0].t); qword nsum=0; for (x=qur[0].s;x!=a;x=pnt[x]) { inside[x]=true; tot[candy[x]]++; nsum+=(suprise[tot[candy[x]]]-suprise[tot[candy[x]]-1])*sweet[candy[x]]; } for (y=qur[0].t;;y=pnt[y]) { inside[y]=true; tot[candy[y]]++; nsum+=(suprise[tot[candy[y]]]-suprise[tot[candy[y]]-1])*sweet[candy[y]]; if (y==a)break; } qur[0].ans=nsum; path pnow(qur[0].s,qur[0].t); path pwalk; for (int i=1;i<=topq;i++) { for (int kk=0;kk<2;kk++) { if (kk==0) pwalk=path(qur[i-1].s,qur[i].s); else pwalk=path(qur[i-1].t,qur[i].t); pwalk.get_path(step,tops); bool flag=true; for (int j=0;j<=tops+1;j++) { if (j!=tops+1 && inside[step[j]]) { inside[step[j]]=false; tot[candy[step[j]]]--; nsum+=(suprise[tot[candy[step[j]]]]-suprise[tot[candy[step[j]]]+1])*sweet[candy[step[j]]]; }else { if (flag) { inside[step[j-1]]=true; tot[candy[step[j-1]]]++; nsum+=(suprise[tot[candy[step[j-1]]]]-suprise[tot[candy[step[j-1]]]-1])*sweet[candy[step[j-1]]]; flag=false; } if (j==tops+1)break; inside[step[j]]=true; tot[candy[step[j]]]++; nsum+=(suprise[tot[candy[step[j]]]]-suprise[tot[candy[step[j]]]-1])*sweet[candy[step[j]]]; } } } if (qur[i-1].upper_pos<qur[i].upper_pos) { for (int j=qur[i-1].upper_pos;j<qur[i].upper_pos;j++) { if (candy[mdfy[j].pos]!=mdfy[j].cold)throw; candy[mdfy[j].pos]=mdfy[j].cnew; if (inside[mdfy[j].pos]) { tot[mdfy[j].cold]--; nsum+=(suprise[tot[mdfy[j].cold]]-suprise[tot[mdfy[j].cold]+1])*sweet[mdfy[j].cold]; tot[mdfy[j].cnew]++; nsum+=(suprise[tot[mdfy[j].cnew]]-suprise[tot[mdfy[j].cnew]-1])*sweet[mdfy[j].cnew]; } } }else { for (int j=qur[i-1].upper_pos-1;j>=qur[i].upper_pos;j--) { if (candy[mdfy[j].pos]!=mdfy[j].cnew)throw; candy[mdfy[j].pos]=mdfy[j].cold; if (inside[mdfy[j].pos]) { tot[mdfy[j].cnew]--; nsum+=(suprise[tot[mdfy[j].cnew]]-suprise[tot[mdfy[j].cnew]+1])*sweet[mdfy[j].cnew]; tot[mdfy[j].cold]++; nsum+=(suprise[tot[mdfy[j].cold]]-suprise[tot[mdfy[j].cold]-1])*sweet[mdfy[j].cold]; } } } qur[i].ans=nsum; } sort(qur,qur+topq+1,cmp_qur_id); for (int i=0;i<=topq;i++) printf("%lld\n",qur[i].ans); }
by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载
本博客已停用,新博客地址:http://mhy12345.xyz