zoukankan      html  css  js  c++  java
  • bzoj3052: [wc2013]糖果公园

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 using namespace std;
      7 #define maxn 100005
      8 typedef long long ll;
      9 ll ans,Ans[maxn];
     10 int n,m,q,temp,cnt1,deep[maxn],b[maxn],sum[maxn],block[maxn],Log[maxn],bz[maxn][21],a[maxn],dfn[maxn],tot,now[maxn],prep[maxn<<1],son[maxn<<1],wi[maxn],vi[maxn];
     11 bool can[maxn];
     12 struct Tsegment{
     13     int l,r,id;
     14 }qs[maxn];
     15 struct Fsegment{
     16     int u,v,bo,last;
     17 }ch[maxn];
     18 void read(int &x){
     19     x=0; int f=1; char Ch;
     20     for (Ch=getchar();Ch<'0'||Ch>'9';Ch=getchar()) if (Ch=='-') f=-1;
     21     for (;Ch>='0'&&Ch<='9';Ch=getchar()) x=x*10+Ch-'0'; x*=f;
     22 }
     23 bool comp(Tsegment x,Tsegment y){
     24     if (block[dfn[x.l]]!=block[dfn[y.l]]) return block[dfn[x.l]]<block[dfn[y.l]];
     25     if (block[dfn[x.r]]!=block[dfn[y.r]]) return block[dfn[x.r]]<block[dfn[y.r]];
     26     return x.id<y.id;
     27 }
     28 void add(int x,int y){
     29     prep[++tot]=now[x],now[x]=tot,son[tot]=y;
     30 }
     31 void dfs(int x,int fa){
     32     dfn[x]=++temp,bz[x][0]=fa,deep[x]=deep[fa]+1;
     33     for (int i=now[x],so=son[i];i;i=prep[i],so=son[i]){
     34         if (so==fa) continue;
     35         dfs(so,x);
     36     }
     37 }
     38 int Lca(int x,int y){
     39     if (x==y) return x;
     40     if (deep[x]<deep[y]) swap(x,y);
     41     while (deep[x]>deep[y]) x=bz[x][Log[deep[x]-deep[y]]];
     42     if (x==y) return x;
     43     while (bz[x][0]!=bz[y][0]){
     44         for (int i=20;i>=0;i--)
     45             if (bz[x][i]!=bz[y][i]){
     46                 x=bz[x][i],y=bz[y][i];
     47                 break;
     48             }
     49     }
     50     return bz[x][0];
     51 }
     52 void prepare(){
     53     temp=sqrt(n); 
     54     for (int i=1;i<=20;i++){
     55         for (int j=1;j<=n;j++){
     56             bz[j][i]=bz[bz[j][i-1]][i-1];
     57         }
     58     }
     59     for (int i=1;i<=n;i++) block[i]=(i-1)/temp+1;
     60 }
     61 void modify(int x){
     62     if (can[x]==0){
     63         can[x]=1;
     64         sum[a[x]]++;
     65         ans+=(1LL*wi[sum[a[x]]]*vi[a[x]]);
     66     }else{
     67         can[x]=0;
     68         ans-=(1LL*wi[sum[a[x]]]*vi[a[x]]);
     69         sum[a[x]]--;
     70     }
     71 }
     72 void change(int x,int y){
     73     for (;x!=y;){
     74         if (deep[x]<deep[y]) swap(x,y);
     75         modify(x); x=bz[x][0];
     76     }
     77 }
     78 void work(){
     79     memset(sum,0,sizeof(sum));
     80     memset(can,0,sizeof(can));
     81     temp=0,ans=qs[0].l=qs[0].r=0;
     82     for (int u,v,w,x,y,i=1;i<=cnt1;i++){
     83         u=qs[i].id;
     84         if (temp<=u){
     85             for (int j=temp;j<=u;j++){
     86                 if (ch[j].bo==0) continue;
     87                 x=ch[j].u,y=ch[j].v;
     88                 if (can[x]==1) modify(x),a[x]=y,modify(x);
     89                 else a[x]=y;
     90             }
     91         }else{
     92             for (int j=temp;j>=u;j--){
     93                 if (ch[j].bo==0) continue;
     94                 x=ch[j].u,y=ch[j].v;
     95                 if (can[x]==1) modify(x),a[x]=ch[j].last,modify(x);
     96                 else a[x]=ch[j].last;
     97             }
     98         } temp=u;
     99         int lca=Lca(qs[i].l,qs[i].r);
    100         change(qs[i-1].l,qs[i].l);
    101         change(qs[i-1].r,qs[i].r);
    102         modify(lca);
    103         Ans[qs[i].id]=ans;
    104         modify(lca);
    105     }
    106 }
    107 int main(){
    108     read(n),read(m),read(q);
    109     for (int i=1;i<=n;i++) Log[i]=log2(i);
    110     for (int i=1;i<=m;i++) read(vi[i]);
    111     for (int i=1;i<=n;i++) read(wi[i]);
    112     tot=0,memset(now,0,sizeof(now));
    113     for (int i=1,u,v;i<n;i++){
    114         read(u),read(v);
    115         add(u,v),add(v,u);
    116     }
    117     for (int i=1;i<=n;i++) read(a[i]);
    118     memset(deep,0,sizeof(deep));
    119     temp=cnt1=0,dfs(1,0);
    120     prepare();
    121     for (int i=1;i<=q;i++) ch[i].bo=0;
    122     for (int type,x,y,i=1;i<=q;i++){
    123         read(type),read(x),read(y);
    124         if (type==1){
    125             qs[++cnt1].id=i,qs[cnt1].l=x,qs[cnt1].r=y;
    126             if (dfn[x]>dfn[y]) swap(qs[cnt1].l,qs[cnt1].r);
    127         }else{
    128             ch[i].u=x,ch[i].v=y,ch[i].bo=1;
    129         }
    130     }
    131     sort(qs+1,qs+cnt1+1,comp);
    132     for (int i=1;i<=n;i++) b[i]=a[i];
    133     for (int i=1;i<=q;i++){
    134         if (ch[i].bo==0) continue;
    135         ch[i].last=b[ch[i].u],b[ch[i].u]=ch[i].v;
    136     }
    137     work();
    138     for (int i=1;i<=q;i++){
    139         if (ch[i].bo==1) continue;
    140         printf("%lld
    ",Ans[i]);
    141     }
    142     return 0;
    143 }
    View Code

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3052

    题目大意:

    做法:带修改的树上莫队算法。

    我们对所有询问排序,怎么排序呢?按左端点所在块为第一关键字,按右端点所在块为第二关键字,按操作的序号(以下称为时间)为第三关键字排序,然后依次暴力转移即可,每次转移时,先将时间暴力转移,即:若上次做完时间停在2,这次操作的时间戳为5,我们则需要把3~4的修改操作执行,暴力即可,如果上次为5,这次为2,则需要倒着还原修改操作。时间转移后利用对称差转移位置即可。及时更新答案即可,记得用1LL乘一下且用Long Long。

    带修改的树上莫队算法。

  • 相关阅读:
    nginx的高级用法
    在windowsXP中如何配置php环境
    .net面试问答
    GridView的其他用法小总结
    php ajax 中文乱码问题解决办法(接收发送)
    SQL时间函数DateAdd的用法
    GridView选中,编辑,取消,删除
    php如何获取复选框选中的值
    C# 中对xml文件的操作
    将分享按钮加入到页面中
  • 原文地址:https://www.cnblogs.com/OYzx/p/5575539.html
Copyright © 2011-2022 走看看