zoukankan      html  css  js  c++  java
  • bzoj 3626

    链剖,居然还可以这样求LCA,学习了orz

    这题很显然看出我还掌握离线处理QAQ

    直接引用清华爷gconeice的题解吧

    显然,暴力求解的复杂度是无法承受的。
    考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案。观察到,深度其实就是上面有几个已标记了的点(包括自身)。所以,我们不妨把 z 到根的路径上的点全部 +1,对于 l 到 r 之间的点询问他们到根路径上的点权和。仔细观察上面的暴力不难发现,实际上这个操作具有叠加性,且可逆。也就是说我们可以对于 l 到 r 之间的点 i,将 i 到根的路径上的点全部 +1, 转而询问 z 到根的路径上的点(包括自身)的权值和就是这个询问的答案。把询问差分下,也就是用 [1, r] − [1, l − 1] 来计算答案,那么现在我们就有一个明显的解法。从 0 到 n − 1 依次插入点 i,即将 i 到根的路径上的点全部+1。离线询问答案即可。我们现在需要一个数据结构来维护路径加和路径求和,显然树链剖分或LCT 均可以完成这个任务。树链剖分的复杂度为 O((n + q)· log n · log n),LCT的复杂度为 O((n + q)· log n),均可以完成任务。至此,题目已经被我们完美解决。

    吐槽一下。。pushdown居然连续写错2个,差一个就要半天QAQ

      1 #include<bits/stdc++.h>
      2 #define inc(i,l,r) for(int i=l;i<=r;i++)
      3 #define dec(i,l,r) for(int i=l;i>=r;i--)
      4 #define link(x) for(edge *j=h[x];j;j=j->next)
      5 #define mem(a) memset(a,0,sizeof(a))
      6 #define inf 201314
      7 #define ll long long
      8 #define succ(x) (1<<x)
      9 #define NM 50000+5
     10 using namespace std;
     11 int read(){
     12     int x=0,f=1;char ch=getchar();
     13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
     14     while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
     15     return x*f;
     16 }
     17 struct info{
     18     ll z,s,size;
     19 }T[8*NM],q[NM],null;
     20 info operator+(const info&x,const info&y){
     21     info f;
     22     f.s=x.s+y.s;
     23     f.size=x.size+y.size;
     24     f.z=0;
     25     return f;
     26 }
     27 struct tmp{
     28     int t,x,z;
     29 }a[2*NM];
     30 bool cmp(tmp x,tmp y){
     31     return x.x<y.x;
     32 }
     33 struct edge{
     34     int t,v;
     35     edge *next;
     36 }e[NM],*h[NM],*p=e;
     37 void add(int x,int y){
     38     p->t=y;p->next=h[x];h[x]=p;p++;
     39 }
     40 int d[NM],f[NM],size[NM],son[NM],id[NM],_id[NM],top[NM],TOP,tot;
     41 int num,n,m,_x,_y,l,r,t;
     42 void dfs1(int x){
     43     link(x)
     44     if(!f[j->t]){
     45         f[j->t]=x;
     46         d[j->t]=d[x]+1;
     47         dfs1(j->t);
     48         size[x]+=size[j->t];
     49         if(size[j->t]>size[son[x]])son[x]=j->t;
     50     }
     51     size[x]++;
     52 }
     53 void dfs2(int x){
     54     top[x]=TOP;id[x]=++tot;_id[tot]=x;
     55     if(son[x])dfs2(son[x]);
     56     link(x)
     57     if(!top[j->t])dfs2(TOP=j->t);
     58 }
     59 void pushdown(int i){
     60     if(T[i].z){
     61         T[i<<1].s+=T[i].z*T[i<<1].size;
     62         T[i<<1|1].s+=T[i].z*T[i<<1|1].size;
     63         T[i<<1].z+=T[i].z;
     64         T[i<<1|1].z+=T[i].z;
     65         T[i].z=0;
     66     }
     67 }
     68 void build(int i,int x,int y){
     69     int t=x+y>>1;
     70     if(x==y){
     71         T[i].size=1;
     72         return;
     73     }
     74     build(i<<1,x,t);build(i<<1|1,t+1,y);
     75     T[i]=T[i<<1]+T[i<<1|1];
     76 }
     77 void ch(int i,int x,int y){
     78     int t=x+y>>1;
     79     if(l<=x&&y<=r){
     80         T[i].z+=1;T[i].s+=T[i].size;
     81         return;
     82     }
     83     if(y<l||r<x)return;
     84     pushdown(i);
     85     ch(i<<1,x,t);ch(i<<1|1,t+1,y);
     86     T[i]=T[i<<1]+T[i<<1|1];
     87 }
     88 void update(int x){
     89     while(top[x]!=1){
     90         l=id[top[x]];r=id[x];
     91         ch(1,1,n);
     92         x=f[top[x]];
     93     }
     94     l=id[1];r=id[x];
     95     ch(1,1,n);
     96 }
     97 info query(int i,int x,int y){
     98     int t=x+y>>1;
     99     pushdown(i);
    100     if(l<=x&&y<=r)return T[i];
    101     if(y<l||r<x)return null;
    102     return query(i<<1,x,t)+query(i<<1|1,t+1,y);
    103 }
    104 int _query(int x){
    105     int s=0;
    106     while(top[x]!=1){
    107         l=id[top[x]];r=id[x];
    108         s+=query(1,1,n).s;
    109         x=f[top[x]];
    110     }
    111     l=id[1];r=id[x];
    112     s+=query(1,1,n).s;
    113     return s;
    114 }
    115 int main(){
    116     n=read();m=read();
    117     inc(i,2,n){
    118         _x=read()+1;
    119         add(_x,i);
    120     }
    121     f[1]=1;null.s=0;
    122     dfs1(1);
    123     dfs2(TOP=1);
    124     build(1,1,n);
    125     inc(i,1,m){
    126         _x=read();_y=read()+1;
    127         q[i].z=read()+1;
    128         a[++num].x=_x;a[num].t=i;a[num].z=1;
    129         a[++num].x=_y;a[num].t=i;a[num].z=0;
    130     }
    131     sort(a+1,a+num+1,cmp);
    132     t=0;
    133     inc(i,1,num){
    134         while(a[i].x>t){
    135             t++;
    136             update(t);
    137 //            printf("%d
    ",T[1].s);
    138         }
    139         _x=a[i].t;
    140         if(a[i].z==1)q[_x].s-=_query(q[_x].z);
    141         else q[_x].s+=_query(q[_x].z);
    142     }
    143     inc(i,1,m)printf("%d
    ",q[i].s%inf);
    144     return 0;
    145 }
    View Code
  • 相关阅读:
    hadoop集群安装
    struts2官方 中文教程 系列十四:主题Theme
    struts2官方 中文教程 系列十三:利用通配符选择方法
    struts2官方 中文教程 系列十二:控制标签
    struts2官方 中文教程 系列十一:使用XML进行表单验证
    struts2官方 中文教程 系列十:Form标签
    struts2官方 中文教程 系列九:Debugging Struts
    struts2官方 中文教程 系列八:异常处理
    struts2官方 中文教程 系列七:消息资源文件
    struts2官方 中文教程 系列六:表单验证
  • 原文地址:https://www.cnblogs.com/onlyRP/p/5046540.html
Copyright © 2011-2022 走看看