[USACO11DEC]牧草种植Grass Planting

题目描述

给出一棵n个节点的树,有m个操作,操作为将一条路径上的边权加一或询问某条边的权值。

输入输出样例

输入样例#1: 复制
4 6 
1 4 
2 4 
3 4 
P 2 3 
P 1 3 
Q 3 4 
P 1 4 
Q 2 4 
Q 1 4 
输出样例#1: 复制
2 
1 
2 
【解题思路】

【code】
  1 // luogu-judger-enable-o2
  2 #include <cstdio>
  3 #include <algorithm>
  4 using namespace std;
  5 int n,a,b,q,x,y,tim,cnt,u,v;
  6 int head[200005],nxt[200005],end[200005],s[200005],t[200005],d[200005],fa[200005];
  7 int son[200005],sum[400005],add[400005],tree[200005],p[200005];
  8 char c;
  9 void Push(int u,int v){
 10     cnt++;
 11     nxt[cnt]=head[u];
 12     head[u]=cnt;
 13     end[cnt]=v;
 14     return ;
 15 }
 16 inline void read(int &a){
 17     a=0;
 18     char ch;
 19     while((ch=getchar())<48);
 20     while(ch>47)
 21         a=(a<<1)+(a<<3)+(ch^48),ch=getchar();
 22 }
 23 inline void swap(int &a,int &b){
 24     int t;
 25     t=a,a=b,b=t;
 26     return ;
 27 }
 28 inline void Pushdown(int w,int l,int r){
 29     add[w<<1]+=add[w];
 30     add[w<<1|1]+=add[w];
 31     sum[w<<1]+=add[w]*l;
 32     sum[w<<1|1]+=add[w]*r;
 33     add[w]=0;
 34 }
 35 inline int Update(int l,int r,int w){
 36     if(l>b||a>r)
 37         return 0;
 38     if(a<=l&&r<=b)
 39         return sum[w];
 40     int m=(l+r)>>1;
 41     if(add[w])
 42         Pushdown(w,m-l+1,r-m);
 43     return Update(l,m,w<<1)+Update(m+1,r,w<<1|1);
 44 }
 45 inline void Query(int l,int r,int w,int x){
 46     if(l>b||a>r)
 47         return;
 48     if(a<=l&&r<=b){
 49         sum[w]+=(r-l+1)*x;
 50         add[w]+=x;
 51         return;
 52     }
 53     int m=(l+r)>>1;
 54     if(add[w])Pushdown(w,m-l+1,r-m);
 55     Query(l,m,w<<1,x);
 56     Query(m+1,r,w<<1|1,x);
 57     sum[w]=sum[w<<1]+sum[w<<1|1];
 58 }
 59 
 60 inline void dfs1(int x){
 61     s[x]=1;
 62     for(int i=head[x];i;i=nxt[i])
 63         if(end[i]!=fa[x]){
 64             int v=end[i];
 65             d[v]=d[x]+1;
 66             fa[v]=x;
 67             dfs1(v);
 68             s[x]+=s[v];
 69             if(s[v]>s[son[x]])
 70                 son[x]=v;
 71         }
 72 }
 73 
 74 inline void dfs2(int x){
 75     tree[x]=++tim;
 76     if(!son[x])
 77         return;
 78     t[son[x]]=t[x];
 79     dfs2(son[x]);
 80     for(int i=head[x];i;i=nxt[i])
 81         if(end[i]!=fa[x]&&end[i]!=son[x]){
 82             t[end[i]]=end[i];
 83             dfs2(end[i]);
 84         }
 85 }
 86 
 87 inline void change(int x,int y){
 88     while(t[x]!=t[y]){
 89         if (d[t[x]]<d[t[y]])swap(x,y);
 90         a=tree[t[x]];
 91         b=tree[x];
 92         Query(1,n,1,1);
 93         x=fa[t[x]];
 94     }
 95     if(d[x]>d[y])swap(x,y);
 96     a=tree[son[x]];
 97     b=tree[y];
 98     Query(1,n,1,1);
 99 }
100 
101 inline int lca(int x,int y){
102     int tmp=0;
103     while(t[x]!=t[y]){
104         if(d[t[x]]<d[t[y]])
105             swap(x,y);
106         a=tree[t[x]];
107         b=tree[x];
108         tmp+=Update(1,n,1);
109         x=fa[t[x]];
110     }
111     if(d[x]>d[y])swap(x,y);
112     a=tree[son[x]];
113     b=tree[y];
114     tmp+=Update(1,n,1);
115     return tmp;
116 }
117 
118 int main(){
119     //freopen("grassplant.in","r",stdin);
120     //freopen("grassplant.out","w",stdout);
121     scanf("%d%d",&n,&q);
122     for(int i=1;i<n;i++){
123         read(u),read(v);
124         Push(u,v),Push(v,u);
125     }
126     dfs1(1);
127     t[1]=1;
128     dfs2(1);
129     while(q--){
130         c=getchar();
131         while(c!='P'&&c!='Q')
132             c=getchar();
133         read(x),read(y);
134         if(c=='P')change(x,y);
135         else printf("%d\n",lca(x,y));
136     }
137     return 0;
138 }

 

上一篇:leetcode1042 Flower Planting With No Adjacent


下一篇:2019 牛客暑期多校 第三场 F Planting Trees (单调队列+尺取)