BZOJ3052: [wc2013]糖果公园

$n \leq 100000$的树,每个点有个糖,$m \leq 100000$种糖,每种糖好吃度$V_i$,吃$j$颗$i$糖会得到愉悦值$V_i*W_j$,$q \leq 100000$个操作:修改一个点上的糖;查询某条链上吃糖的愉悦值。

首先看看能不能用啥数据结构维护。麻烦。好上莫队。

树上的莫队,用dfs的入栈+出栈序可以变区间查询,查询$x$和$y$时,分$x$是否是$y$的祖先、$y$是否是$x$的祖先、两个都不是彼此祖先来查。

莫队的主要复杂度在修改,所以修改只要稍微改一点点东西都会快很多。比如我少了个if就快了10秒。好不卡了没意思。

  1 //#include<iostream>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cstdio>
  5 //#include<queue>
  6 //#include<time.h>
  7 //#include<complex>
  8 #include<algorithm>
  9 #include<stdlib.h>
 10 using namespace std;
 11 
 12 int n,m,lq,bl,tot,lc;
 13 #define maxn 200011
 14 int V[maxn],W[maxn],cnt[maxn],a[maxn],bel[maxn];
 15 struct Ques{int l,r,t,id,biu;}q[maxn];
 16 bool cmp(const Ques &a,const Ques &b) {return bel[a.l]==bel[b.l]?(bel[a.r]==bel[b.r]?a.t<b.t:a.r<b.r):a.l<b.l;}
 17 struct Modi{int x,a,b;}mo[maxn];
 18 
 19 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2;
 20 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
 21 void insert(int x,int y) {in(x,y); in(y,x);}
 22 
 23 int A[maxn],B[maxn],list[maxn],len,dep[maxn],Log[maxn],rmq[maxn][20],lr=0,idr[maxn];
 24 void dfs(int x,int fa)
 25 {
 26     list[++len]=x; A[x]=len; dep[x]=dep[fa]+1; rmq[++lr][0]=x; idr[x]=lr;
 27     for (int i=first[x];i;i=edge[i].next)
 28     {
 29         Edge &e=edge[i]; if (e.to==fa) continue;
 30         dfs(e.to,x); rmq[++lr][0]=x;
 31     }
 32     list[++len]=x; B[x]=len;
 33 }
 34 void makermq()
 35 {
 36     Log[0]=-1; for (int i=1;i<=lr;i++) Log[i]=Log[i>>1]+1;
 37     for (int j=1;j<=18;j++)
 38         for (int i=1,to=lr-(1<<j)+1;i<=to;i++)
 39             rmq[i][j]=dep[rmq[i][j-1]]<dep[rmq[i+(1<<(j-1))][j-1]]?rmq[i][j-1]:rmq[i+(1<<(j-1))][j-1];
 40 }
 41 int lca(int x,int y)
 42 {
 43     if (idr[x]>idr[y]) x^=y^=x^=y; x=idr[x]; y=idr[y];
 44     int l=Log[y-x+1];
 45     return dep[rmq[x][l]]<dep[rmq[y-(1<<l)+1][l]]?rmq[x][l]:rmq[y-(1<<l)+1][l];
 46 }
 47 
 48 #define LL long long
 49 LL ans[maxn],ss; bool have[maxn];
 50 void modify(int x)
 51 {
 52     if (have[list[x]]) ss-=V[a[list[x]]]*1ll*W[cnt[a[list[x]]]],cnt[a[list[x]]]--;
 53     else cnt[a[list[x]]]++,ss+=V[a[list[x]]]*1ll*W[cnt[a[list[x]]]];
 54     have[list[x]]^=1;
 55 }
 56 void timemodify(int L,int R,int x,int v)
 57 {
 58     if ((L<=A[x] && A[x]<=R)^(L<=B[x] && B[x]<=R)) modify(A[x]),a[x]=v,modify(A[x]);
 59     else a[x]=v;
 60 }
 61 
 62 int main()
 63 {
 64     scanf("%d%d%d",&n,&m,&lq);
 65     bl=2185;
 66     for (int i=1;i<=n*2;i++) bel[i]=(i-1)/bl+1; tot=bel[n*2];
 67     for (int i=1;i<=m;i++) scanf("%d",&V[i]);
 68     for (int i=1;i<=n;i++) scanf("%d",&W[i]);
 69     for (int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),insert(x,y);
 70     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
 71     dfs(1,0); makermq();
 72     lc=0;
 73     for (int i=1,op,j=0;i<=lq;i++)
 74     {
 75         scanf("%d",&op);
 76         if (op==1)
 77         {
 78             j++; scanf("%d%d",&q[j].l,&q[q[j].id=j].r); q[j].t=lc;
 79             int l=lca(q[j].l,q[j].r);
 80             if (l==q[j].l || l==q[j].r) {int t=q[j].l; q[j].l=min(A[t],A[q[j].r]); q[j].r=max(A[t],A[q[j].r]); q[j].biu=0;}
 81             else
 82             {
 83                 if (A[q[j].l]<A[q[j].r]) q[j].l=B[q[j].l],q[j].r=A[q[j].r];
 84                 else {int t=q[j].l; q[j].l=B[q[j].r]; q[j].r=A[t];}
 85                 q[j].biu=A[l];
 86             }
 87         }
 88         else
 89         {
 90             lc++; scanf("%d%d",&mo[lc].x,&mo[lc].b);
 91             mo[lc].a=a[mo[lc].x]; a[mo[lc].x]=mo[lc].b;
 92         }
 93     }
 94     lq-=lc;
 95     sort(q+1,q+1+lq,cmp);
 96     
 97     int L=1,R=0,T=lc; ss=0;
 98     for (int i=1;i<=lq;i++)
 99     {
100         while (T<q[i].t) T++,timemodify(L,R,mo[T].x,mo[T].b);
101         while (T>q[i].t) timemodify(L,R,mo[T].x,mo[T].a),T--;
102         while (L<q[i].l) modify(L),L++;
103         while (L>q[i].l) L--,modify(L);
104         while (R<q[i].r) R++,modify(R);
105         while (R>q[i].r) modify(R),R--;
106         if (q[i].biu) modify(q[i].biu);
107         ans[q[i].id]=ss;
108         if (q[i].biu) modify(q[i].biu);
109     }
110     for (int i=1;i<=lq;i++) printf("%lld\n",ans[i]);
111     return 0;
112 }
View Code

 

posted @ 2018-03-16 09:22  Blue233333  阅读(164)  评论(0编辑  收藏  举报