CF343D Water Tree

题目链接

题目翻译(摘自洛谷)

疯狂科学家Mike培养了一颗有根树,由n个节点组成。每个节点是一个要么装满水要么为空的贮水容器. 树的节点用1~n编号,其中根节点为1.对于每个节点的容器,其子节点的容器均在这一容器下方,并且每个节点都由一根可以向下流水的管道与其子节点连接. Mike想要对这棵树做以下操作:
1将节点v注满水. 这样v和其子节点都会充满水.
2将节点v置空. 这样v及其祖先节点(从v到根节点的路径)都会被置空.
3查询当前节点v是否充满水.
初始时,所有节点都为空. Mike已经制定好了他的操作顺序. 在对树进行实验前,他决定先模拟一下操作. 请你帮助Mike得出他操作后的结果.

思路

裸树链剖分,区间修改,单点查询。

  1 #include<iostream>
  2 #include<cstdio>
  3 using namespace std;
  4 const int N=500005;
  5 int n,cnt,dcnt,hd[N];
  6 struct edge
  7 {
  8     int to,nxt;
  9 }v[2*N];
 10 struct node
 11 {
 12     int fa,son,sz,dep,tp,s,e;
 13 }tr[N];
 14 struct segtree
 15 {
 16     int l,r,stat,tag;
 17 }st[4*N];
 18 void addedge(int x,int y)
 19 {
 20     v[++cnt].to=y;
 21     v[cnt].nxt=hd[x];
 22     hd[x]=cnt;
 23 }
 24 void dfs1(int u)
 25 {
 26     tr[u].sz=1;
 27     for(int i=hd[u];i;i=v[i].nxt)
 28         if(v[i].to!=tr[u].fa)
 29         {
 30             tr[v[i].to].fa=u;
 31             tr[v[i].to].dep=tr[u].dep+1;
 32             dfs1(v[i].to);
 33             tr[u].sz+=tr[v[i].to].sz;
 34             if(tr[v[i].to].sz>tr[tr[u].son].sz)
 35                 tr[u].son=v[i].to;
 36         }
 37 }
 38 void dfs2(int u,int top)
 39 {
 40     tr[u].tp=top;
 41     tr[u].s=++dcnt;
 42     if(tr[u].son)
 43     {
 44         dfs2(tr[u].son,top);
 45         for(int i=hd[u];i;i=v[i].nxt)
 46             if(v[i].to!=tr[u].fa&&v[i].to!=tr[u].son)
 47                 dfs2(v[i].to,v[i].to);
 48     }
 49     tr[u].e=dcnt;
 50 }
 51 void build(int num,int l,int r)
 52 {
 53     st[num].l=l,st[num].r=r;
 54     st[num].tag=-1;
 55     if(l==r)
 56         return ;
 57     int mid=(l+r)/2;
 58     build(2*num,l,mid),build(2*num+1,mid+1,r);
 59 }
 60 void pushdown(int num)
 61 {
 62     if(st[num].tag!=-1)
 63     {
 64         if(st[num].l!=st[num].r)
 65         {
 66             st[2*num].stat=st[2*num+1].stat=st[num].tag;
 67             st[2*num].tag=st[2*num+1].tag=st[num].tag;
 68         }
 69         st[num].tag=-1;
 70     }
 71 }
 72 void change(int num,int l,int r,int z)
 73 {
 74     if(l>st[num].r||r<st[num].l)
 75         return ;
 76     if(st[num].l>=l&&st[num].r<=r)
 77     {
 78         st[num].tag=st[num].stat=z;
 79         return ;
 80     }
 81     pushdown(num);
 82     change(2*num,l,r,z),change(2*num+1,l,r,z);
 83 }
 84 int query(int num,int x)
 85 {
 86     if(st[num].l>x||st[num].r<x)
 87         return 0;
 88     if(st[num].l==st[num].r)
 89         return st[num].stat;
 90     pushdown(num);
 91     return query(2*num,x)+query(2*num+1,x);
 92 }
 93 void fnd(int x)
 94 {
 95     int f1=tr[x].tp;
 96     while(f1!=1)
 97     {
 98         change(1,tr[f1].s,tr[x].s,0);
 99         x=tr[f1].fa,f1=tr[x].tp;
100     }
101     change(1,1,tr[x].s,0);
102 }
103 int main()
104 {
105     scanf("%d",&n);
106     for(int i=1;i<=n-1;i++)
107     {
108         int x,y;
109         scanf("%d%d",&x,&y);
110         addedge(x,y),addedge(y,x);
111     }
112     dfs1(1);
113     dfs2(1,1);
114     build(1,1,n);
115     int q,x,y;
116     scanf("%d",&q);
117     while(q--)
118     {
119         scanf("%d%d",&x,&y);
120         switch(x)
121         {
122             case 1:
123                 change(1,tr[y].s,tr[y].e,1);
124                 break;
125             case 2:
126                 fnd(y);
127                 break;
128             case 3:
129                 printf("%d
",query(1,tr[y].s));
130                 break;
131         }
132     }
133     return 0;
134 }
原文地址:https://www.cnblogs.com/fantasquex/p/9355715.html