zoukankan      html  css  js  c++  java
  • 【BZOJ】【3052】【WC2013】糖果公园

    树分块

      老早(大约一个月以前?)就听说这道神题了……orz rausen

      一直拖到现在才做……发现还是不会呢= = 只好也去Orz了Hzwer和zky

      http://hzwer.com/5250.html
      http://blog.csdn.net/iamzky/article/details/42125999
     

      这个树上莫队真的蛮神奇的……

      1.对于每个查询,记录它是在第几次修改之后的;

      2.以左端点所在块为第一关键字、右端点所在块为第二关键字、时间(第几次修改之后的查询)为第三关键字进行排序;

      3.对于每个查询,先进行时间上的移动(这个只需对变化了的点进行单点修改即可,有点小Z的袜子中 +1-1的感觉)再进行查询序列的移动(用之前讲的vfk的方法……)至于第二步就跟普通的树分块一样了么……

    注意:由于时间移动既有向前也有向后的,所以除了要记录是把哪个点变成了什么糖果,还要记录变化前的原来的状态(时光回溯时用)(用“时光回溯”这个名字是不是十分高大上~~)

    错误:1.所有数据点的答案范围都是long long!!

       2.读入单点修改糖果种类的时候,pre[x]=y; 写成了 pre[c2]=y;  QAQ唉细节啊细节!!!pre数组是对点进行“时光回溯”保存的,不是对修改序号进行保存!!!理解不到位啊……(白问大视野要数据了……)

      1 /**************************************************************
      2     Problem: 3052
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:117744 ms
      7     Memory:25256 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 3052
     11 #include<cmath>
     12 #include<cstdio>
     13 #include<cstdlib>
     14 #include<cstring>
     15 #include<iostream>
     16 #include<algorithm>
     17 #define rep(i,n) for(int i=0;i<n;++i)
     18 #define F(i,j,n) for(int i=j;i<=n;++i)
     19 #define D(i,j,n) for(int i=j;i>=n;--i)
     20 using namespace std;
     21  
     22 int getint(){
     23     int v=0,sign=1; char ch=getchar();
     24     while(!isdigit(ch)) {if(ch=='-') sign=-1; ch=getchar();}
     25     while(isdigit(ch)) {v=v*10+ch-'0'; ch=getchar();}
     26     return v*=sign;
     27 }
     28 typedef long long LL;
     29 /******************tamplate*********************/
     30 const int N=100086;
     31 LL w[N],v[N];
     32 int n,m,Q;
     33 int head[N],next[N<<1],to[N<<1],cnt;
     34 void add(int x,int y){
     35     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
     36     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt;
     37 }
     38 /*******************edge************************/
     39 int B;
     40 int st[N],top,deep[N],belong[N],tot;
     41 int fa[N][25],bin[25];
     42 void dfs(int x){
     43     int bottom=top;
     44     F(i,1,20)
     45         if(deep[x]>=bin[i])
     46             fa[x][i]=fa[fa[x][i-1]][i-1];
     47         else break;
     48     for(int i=head[x];i;i=next[i])
     49         if (to[i]!=fa[x][0]){
     50             fa[to[i]][0]=x;
     51             deep[to[i]]=deep[x]+1;
     52             dfs(to[i]);
     53             if(top-bottom>=B){
     54                 ++tot;
     55                 while(top!=bottom)
     56                     belong[st[top--]]=tot;
     57             }
     58         }
     59     st[++top]=x;
     60 }
     61 int LCA(int x,int y){
     62     if(deep[x]<deep[y]) swap(x,y);
     63     int t=deep[x]-deep[y];
     64     for(int i=0;bin[i]<=t;i++)
     65         if(t&bin[i]) x=fa[x][i];
     66     D(i,20,0)
     67         if(fa[x][i]!=fa[y][i])
     68             x=fa[x][i],y=fa[y][i];
     69     if(x==y) return x;
     70     return fa[x][0];
     71 }
     72 /*********************dfs&&LCA******************/
     73 struct ques{
     74     int x,y,ti,num;
     75     bool operator < (const ques&now)const{
     76         if(belong[x]==belong[now.x]){
     77             if(belong[y]==belong[now.y]) return ti<now.ti;
     78             else return belong[y]<belong[now.y];
     79         }
     80         else return belong[x]<belong[now.x];
     81     }
     82 }q[N];
     83 struct Time{
     84     int x,y,pre;
     85 }change[N];
     86 int pre[N];
     87  
     88 LL ans=0,answer[N];
     89 int c[N],num[N],now;
     90 bool used[N];
     91 /*****************分块变量声明******************/
     92 void work(int x){
     93     if (used[x]){
     94         ans-=v[c[x]]*w[num[c[x]]]; num[c[x]]--; used[x]=0;
     95     }
     96     else{
     97         num[c[x]]++; ans+=v[c[x]]*w[num[c[x]]]; used[x]=1;
     98     }
     99 }
    100 void Xor(int x,int y){
    101     while(x!=y)
    102         if(deep[x]>deep[y]) {work(x);x=fa[x][0];}
    103         else {work(y); y=fa[y][0];}
    104 }
    105 void Change(int x,int y){//将点x的糖果改为第y种 (权值改为y) 
    106     if(used[x]){work(x); c[x]=y; work(x);}
    107     else c[x]=y;
    108 }
    109 void TimeMachine(int tarti){
    110     for(int i=now+1;i<=tarti;i++) Change(change[i].x,change[i].y);
    111     for(int i=now;i>tarti;i--) Change(change[i].x,change[i].pre);
    112     now=tarti;
    113 }
    114 /*****************分块函数声明******************/
    115 int main(){
    116     bin[0]=1; F(i,1,20) bin[i]=bin[i-1]<<1;
    117      
    118     n=getint(); m=getint(); Q=getint();
    119     B=pow(n,2.0/3.0);
    120     int x,y;
    121     F(i,1,m) v[i]=getint();//美味指数 
    122     F(i,1,n) w[i]=getint();//新奇指数 
    123     F(i,2,n){
    124         x=getint(); y=getint();
    125         add(x,y);
    126     }
    127  
    128     dfs(1);
    129     tot++;
    130     while(top) belong[st[top--]]=tot;
    131     F(i,1,n) pre[i]=c[i]=getint();//每个节点的糖果种类 
    132      
    133     int cmd,c1=0,c2=0;
    134     F(i,1,Q){
    135         cmd=getint(); x=getint(); y=getint();
    136         if (cmd){
    137             c2++;
    138             if(belong[x]>belong[y]) swap(x,y);
    139             q[c2]=(ques){x,y,c1,c2};//记录是第几次修改之后的查询
    140         }
    141         else{
    142             c1++;
    143             change[c1]=(Time){x,y,pre[x]};
    144             pre[x]=y;
    145             //有点前向星的感觉,pre[i]保存第i个节点当前是什么种类的糖果
    146         }
    147     }
    148     sort(q+1,q+c2+1);
    149     //读入&&初始化 end
    150  
    151     int lca=LCA(q[1].x,q[1].y);
    152     TimeMachine(q[1].ti);
    153     Xor(q[1].x,q[1].y);
    154     work(lca);
    155     answer[q[1].num]=ans;
    156     work(lca);
    157     F(i,2,c2){
    158         TimeMachine(q[i].ti);
    159         Xor(q[i-1].x,q[i].x);
    160         Xor(q[i-1].y,q[i].y);
    161         lca=LCA(q[i].x,q[i].y);
    162         work(lca);
    163         answer[q[i].num]=ans;
    164         work(lca);
    165     }
    166     F(i,1,c2) printf("%lld
    ",answer[i]);
    167     return 0;
    168 }
    View Code
  • 相关阅读:
    在图片上面添加字体
    wampserver php 识别不了>或者尖括号 php.ini中short_open_tag设置方法
    [P5162] WD与积木
    [P5170] 类欧几里得算法
    [P5172] Sum
    [HEOI2014] 大工程
    [P4721] 分治 FFT
    [BJOI2017] 树的难题
    [P4886] 快递员
    [CERC2014] Virus synthesis
  • 原文地址:https://www.cnblogs.com/Tunix/p/4251701.html
Copyright © 2011-2022 走看看