zoukankan      html  css  js  c++  java
  • uoj #58 【WC2013】糖果公园

    题面:http://uoj.ac/problem/58

    正解:树上带修改莫队。

    首先Orz vfk大神,树上莫队的套路还是很厉害的。。http://vfleaking.blog.163.com/blog/static/174807634201311011201627/

    我们考虑普通的树上莫队。我们要先把树分好块,分块的方式和王室联邦是一样的,即限定块的大小来分块。当我们限定了块的大小以后,我们能保证块的直径不超过块的大小,于是在同一个块内移动是可以保证复杂度的。然后树上莫队每次就是上一个询问的$u$到这一个询问的$u$的路径修改一遍,$v$也是一样,注意每次询问$LCA$都是要特判的。加入修改操作以后,我们考虑普通莫队算法,就是把块的大小改成$O(n^{frac{2}{3}})$,然后能够保证总复杂度是$O(n^{frac{5}{3}})$的,每次询问记录它之前要执行的修改次数。然后我们就可以直接暴力搞了,如果修改多了就撤回,少了就加上。这样我们就能完美地解决这道题了。

      1 //It is made my wfj_2048~
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <complex>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <cstdio>
      8 #include <cmath>
      9 #define inf (1<<30) 
     10 #define N (100010)
     11 #define il inline
     12 #define RG register
     13 #define ll long long
     14 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     15 
     16 using namespace std;
     17 
     18 struct node1{ int u,v,t,i; }q1[N];
     19 struct node2{ int x,v,pre; }q2[N];
     20 struct edge{ int nt,to; }g[2*N];
     21 
     22 int head[N],v[N],w[N],top[N],fa[N],son[N],bl[N],sz[N],dep[N],dfn[N],pre[N],col[N],c[N],st[N],vis[N],n,m,Q,tp,Lca,num,cnt,ccnt,cnt1,cnt2,block;
     23 ll ans[N],Ans;
     24 
     25 il int gi(){
     26     RG int x=0,q=1; RG char ch=getchar();
     27     while((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     28     if (ch=='-') q=-1,ch=getchar();
     29     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
     30     return q*x;
     31 }
     32 
     33 il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; }
     34 
     35 int cmpt(const node1 &a,const node1 &b){
     36     if (bl[a.u]==bl[b.u] && bl[a.v]==bl[b.v]) return a.t<b.t;
     37     if (bl[a.u]==bl[b.u]) return bl[a.v]<bl[b.v]; return bl[a.u]<bl[b.u];
     38 }
     39 
     40 il void dfs1(RG int x,RG int p){
     41     fa[x]=p,sz[x]=1,dep[x]=dep[p]+1; RG int v;
     42     for (RG int i=head[x];i;i=g[i].nt){
     43     v=g[i].to; if (v==p) continue;
     44     dfs1(v,x); sz[x]+=sz[v];
     45     if (sz[son[x]]<=sz[v]) son[x]=v;
     46     }
     47     return;
     48 }
     49 
     50 il void dfs2(RG int x,RG int p,RG int anc){
     51     top[x]=anc,dfn[x]=++cnt; RG int ttp=tp;
     52     if (son[x]) dfs2(son[x],x,anc); RG int v;
     53     if (tp-ttp>=block){ ccnt++; while (tp>ttp) bl[st[tp--]]=ccnt; } //按大小分块
     54     for (RG int i=head[x];i;i=g[i].nt){
     55     v=g[i].to; if (v==p || v==son[x]) continue; dfs2(v,x,v);
     56     if (tp-ttp>=block){ ccnt++; while (tp>ttp) bl[st[tp--]]=ccnt; }
     57     }
     58     st[++tp]=x; return;
     59 }
     60 
     61 il int lca(RG int u,RG int v){
     62     while (top[u]!=top[v]){
     63     if (dep[top[u]]<dep[top[v]]) swap(u,v);
     64     u=fa[top[u]];
     65     }
     66     return dep[u]<dep[v] ? u : v;
     67 }
     68 
     69 il void update(RG int x){
     70     if (!vis[x]) vis[x]=1,c[col[x]]++,Ans+=(ll)w[c[col[x]]]*(ll)v[col[x]];
     71     else vis[x]=0,Ans-=(ll)w[c[col[x]]]*(ll)v[col[x]],c[col[x]]--; return;
     72 }
     73 
     74 il void modify(RG int x,RG int v){ if (!vis[x]) col[x]=v; else update(x),col[x]=v,update(x); return; }
     75 
     76 il void change(RG int x,RG int y){
     77     while (x!=y){
     78     if (dep[x]<dep[y]) update(y),y=fa[y];
     79     else update(x),x=fa[x];
     80     }
     81     return;
     82 }
     83 
     84 il void work(){
     85     n=gi(),m=gi(),Q=gi(),block=pow(n,0.6); RG int type,x,y;
     86     for (RG int i=1;i<=m;++i) v[i]=gi();
     87     for (RG int i=1;i<=n;++i) w[i]=gi();
     88     for (RG int i=1;i<n;++i) x=gi(),y=gi(),insert(x,y),insert(y,x);
     89     while (tp) st[tp--]=ccnt;
     90     for (RG int i=1;i<=n;++i) col[i]=gi(),pre[i]=col[i]; dfs1(1,0),dfs2(1,0,1);
     91     for (RG int i=1;i<=Q;++i){
     92     type=gi(),x=gi(),y=gi();
     93     if (type){
     94         if (dfn[x]>dfn[y]) swap(x,y);
     95         q1[++cnt1].u=x,q1[cnt1].v=y,q1[cnt1].t=cnt2,q1[cnt1].i=cnt1;
     96     }
     97     if (!type) q2[++cnt2].x=x,q2[cnt2].v=y,q2[cnt2].pre=pre[x],pre[x]=y;
     98     }
     99     sort(q1+1,q1+cnt1+1,cmpt); cnt2=q1[1].t;
    100     for (RG int i=1;i<=cnt2;++i) modify(q2[i].x,q2[i].v);
    101     change(q1[1].u,q1[1].v),Lca=lca(q1[1].u,q1[1].v);
    102     update(Lca),ans[q1[1].i]=Ans,update(Lca); //LCA特判
    103     for (RG int i=2;i<=cnt1;++i){
    104     while (cnt2<q1[i].t) cnt2++,modify(q2[cnt2].x,q2[cnt2].v);
    105     while (cnt2>q1[i].t) modify(q2[cnt2].x,q2[cnt2].pre),cnt2--;
    106     change(q1[i-1].u,q1[i].u),change(q1[i-1].v,q1[i].v);
    107     Lca=lca(q1[i].u,q1[i].v),update(Lca),ans[q1[i].i]=Ans,update(Lca);
    108     }
    109     for (RG int i=1;i<=cnt1;++i) printf("%I64d
    ",ans[i]); return; //这几天用windows。。
    110 }
    111 
    112 int main(){
    113     File("park");
    114     work();
    115     return 0;
    116 }
  • 相关阅读:
    Spyder | 关于报错No module named 'PyQt5.QtWebKitWidgets'
    Java基础(11) | 接口
    Java基础(10) | 抽象
    Java基础(9) | 继承
    Java基础(7) | String
    Java基础(6) | ArrayList
    CodeBlocks17.12配置GNU GCC + 汉化
    图片懒加载
    Mac安装Mysql 超详细(转载)
    剑指 Offer 03. 数组中重复的数字
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6592430.html
Copyright © 2011-2022 走看看