[Usaco2011 Dec]Grass Planting
Description
Farmer John has N barren pastures connected by N-1 bidirectional roads, such that there is exactly o
ne path between any two pastures. Bessie, a cow who loves her grazing time, often complains about ho
w there is no grass on the roads between pastures. Farmer John loves Bessie very much, and today he
is finally going to plant grass on the roads. He will do so using a procedure consisting of M steps
.
At each step one of two things will happen:
- FJ will choose two pastures, and plant a patch of grass along each road in between the two pastures, or,
- Bessie will ask about how many patches of grass on a particular road, and Farmer John must answer her question.
Farmer John is a very poor counter -- help him answer Bessie's questions!
大致题意: 维护一棵树,支持两种操作:
P x y x到y路径上的每条边的值+1;
Q x y 询问x到y路径上所有边的值的和。
ne path between any two pastures. Bessie, a cow who loves her grazing time, often complains about ho
w there is no grass on the roads between pastures. Farmer John loves Bessie very much, and today he
is finally going to plant grass on the roads. He will do so using a procedure consisting of M steps
.
At each step one of two things will happen:
- FJ will choose two pastures, and plant a patch of grass along each road in between the two pastures, or,
- Bessie will ask about how many patches of grass on a particular road, and Farmer John must answer her question.
Farmer John is a very poor counter -- help him answer Bessie's questions!
大致题意: 维护一棵树,支持两种操作:
P x y x到y路径上的每条边的值+1;
Q x y 询问x到y路径上所有边的值的和。
Input
Line 1: Two space-separated integers N and M.
Lines 2..N: Two space-separated integers describing the endpoints of a road.
Lines N+1..N+M: Line i+1 describes step i. The first character of the line is either P or Q, which d
escribes whether or not FJ is planting grass or simply querying. This is followed by two space-separ
ated integers A_i and B_i (1 ≤A_i, B_i ≤N) which describe FJ's action or query.
第一行两个正整数,N,M表示点数和操作数;
接下来N-1行每行两个数表示一条边;
接下来M行表示M个操作,每行形如P x y或Q x y。
2≤N≤100,000,1≤M≤100,000。
Lines 2..N: Two space-separated integers describing the endpoints of a road.
Lines N+1..N+M: Line i+1 describes step i. The first character of the line is either P or Q, which d
escribes whether or not FJ is planting grass or simply querying. This is followed by two space-separ
ated integers A_i and B_i (1 ≤A_i, B_i ≤N) which describe FJ's action or query.
第一行两个正整数,N,M表示点数和操作数;
接下来N-1行每行两个数表示一条边;
接下来M行表示M个操作,每行形如P x y或Q x y。
2≤N≤100,000,1≤M≤100,000。
Output
Lines 1..???: Each line has the answer to a query, appearing in the same order as the queries appear in the input.
M行,对应相应询问的答案。
M行,对应相应询问的答案。
Sample Input
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
Sample Output
2
1
2
来写此题的一定都是学过树剖的了吧。
这道题用到了线段树的区间修改,难道真的只要在单点修改的情况下在线段树中使用lazy标记来进行区间修改就行了么
答案是否定的!!
你或许能过样例,但是肯定是红色的wa
我们知道树剖要不断的去跳重链,如果你要修改的区间不在一条重链上,那就会出错哦(样例很坑哦)
所以需要在加lazy标记的同时再不断地跳重链
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 using namespace std; 5 const int N=200001; 6 int n,m,cnt,now,pre[N],f[N],nxt[N],h[N],top[N],id[N],size[N],dep[N],sum; 7 struct oo{int a,b,v,lazy;}s[N*3]; 8 char p[9]; 9 void dfs(int x) 10 { 11 size[x]=1; 12 for(int i=h[x];i;i=nxt[i]) 13 { 14 if(pre[i]==f[x])continue; 15 dep[pre[i]]=dep[x]+1; 16 f[pre[i]]=x; 17 dfs(pre[i]); 18 size[x]+=size[pre[i]]; 19 } 20 } 21 void dfs2(int x,int f) 22 { 23 int k=0; 24 id[x]=++cnt; 25 top[x]=f; 26 for(int i=h[x];i;i=nxt[i]) 27 if(size[pre[i]]>size[k]&&dep[pre[i]]>dep[x])k=pre[i]; 28 if(!k)return ; 29 dfs2(k,f); 30 for(int i=h[x];i;i=nxt[i]) 31 if(dep[pre[i]]>dep[x]&&pre[i]!=k) 32 dfs2(pre[i],pre[i]); 33 } 34 void ins(int x,int y) 35 { 36 pre[++now]=y; 37 nxt[now]=h[x]; 38 h[x]=now; 39 } 40 void build(int x,int l,int r) 41 { 42 s[x].a=l,s[x].b=r; 43 if(l==r)return ; 44 build(x<<1,l,l+r>>1); 45 build(x<<1|1,(l+r>>1)+1,r); 46 } 47 void pushdown(int x) 48 { 49 int l=x<<1,r=x<<1|1; 50 s[l].lazy+=s[x].lazy,s[r].lazy+=s[x].lazy; 51 s[l].v+=s[x].lazy*(s[l].b-s[l].a+1); 52 s[r].v+=s[x].lazy*(s[r].b-s[r].a+1); 53 s[x].lazy=0; 54 } 55 void get(int x,int l,int r) 56 { 57 if(s[x].lazy)pushdown(x); 58 if(s[x].a>=l&&r>=s[x].b) 59 sum+=s[x].v; 60 else 61 { 62 int mid=s[x].a+s[x].b>>1; 63 if(l<=mid)get(x<<1,l,r); 64 if(r>mid)get(x<<1|1,l,r); 65 } 66 } 67 void qsum(int x,int y) 68 { 69 sum=0; 70 while(top[x]!=top[y]) 71 { 72 if(dep[top[x]]<dep[top[y]])swap(x,y); 73 get(1,id[top[x]],id[x]); 74 x=f[top[x]]; 75 } 76 if(id[x]>id[y])swap(x,y); 77 get(1,id[x]+1,id[y]); 78 } 79 void change(int x,int l,int r) 80 { 81 if(s[x].lazy)pushdown(x); 82 if(l<=s[x].a&&r>=s[x].b) 83 { 84 s[x].v+=s[x].b-s[x].a+1; 85 s[x].lazy++; 86 return ; 87 } 88 int mid=s[x].a+s[x].b>>1; 89 if(l<=mid)change(x<<1,l,r); 90 if(r>mid)change(x<<1|1,l,r); 91 s[x].v=s[x<<1].v+s[x<<1|1].v; 92 } 93 void qchange(int x,int y) 94 { 95 while(top[x]!=top[y]) 96 { 97 if(dep[top[x]]<dep[top[y]])swap(x,y); 98 change(1,id[top[x]],id[x]); 99 x=f[top[x]]; 100 } 101 if(id[x]>id[y])swap(x,y); 102 change(1,id[x]+1,id[y]); 103 } 104 int main() 105 { 106 scanf("%d",&n); 107 scanf("%d",&m); 108 for(int i=1,x,y;i<n;i++) 109 { 110 scanf("%d%d",&x,&y); 111 ins(x,y);ins(y,x); 112 } 113 dfs(1);dfs2(1,1); 114 build(1,1,n); 115 for(int i=1,x,y;i<=m;i++) 116 { 117 scanf("%s%d%d",p+1,&x,&y); 118 if(p[1]=='Q') 119 { 120 qsum(x,y); 121 printf("%d\n",sum); 122 } 123 if(p[1]=='P')qchange(x,y); 124 } 125 }