Observing the Tree Problem Code: QUERY
Submit
Chef gives you a tree, consisting of N nodes. The nodes are numbered from 1 to N, and each node has an integer, which is equal to 0 initially. Then, Chef asks you to perform M queries.
The first type of queries is changing: here, you are given integers X, Y, A and B. Add Ato the integer, associated with the node X, then add A+B to the integer, associated with the second node on the way from X to Y, then add A+2*B to the integer, associated with the third node on the way from X to Y, and so on. As you know, there is only one simple path from X to Y.
The second type of queries is a question: here, you are given integers X and Y. Output the sum of all integers, associated with nodes on the way from X to Y.
The third type of queries is a rollback: here, you are given an integer X. All the integers associated with the nodes return to the state after the X-th changing query. If X is 0, then all of them become equal to zero, as in the very beginning.
Input
The first line of an input consists of two integers - N and M.
Then, N−1 lines follow. These N−1 lines describe the tree structure. Each line consists of two integers - X and Y, and that means that there is an edge between node X and node Y.
Then, M lines follow. A single line denotes a single query, which has one of the following forms: (See the sample for the detailed explanation)
- c X1 Y1 A B - changing query,
- q X1 Y1 - question query,
- l X1 - rollback query.
As you can see, the numbers X and Y aren't given to you directly. For the rollbackquery, actual number X will be equal to (X1+lastans) modulo (total number ofchanging queries before this query + 1). For the changing and question queries, Xwill be equal to ((X1+lastans) modulo N)+1 and Y will be equal to ((Y1+lastans) modulo N)+1, where lastans denotes the last number that you have output, or zero if you haven't output any numbers yet.
Output
For each question query output the answer on a single line.
Constraints
- 1 ≤ N, M ≤ 100000 (105)
- 0 ≤ A, B ≤ 1000
- 0 ≤ X1, Y1 ≤ 100000 (105)
Example
Input: 5 7 1 2 2 3 3 4 4 5 c 1 4 2 3 c 2 3 5 10 q 1 3 l 1 q 1 3 l 1 q 1 3 Output: 35 0 15
Explanation
As you can see, the tree in the sample is like a line. Let's denote the first state of integers 0 0 0 0 0, where the i-th integer means the integer associated with the node i.
In the first changing query "c 1 4 2 3", the actual numbers are X = (1 + 0) modulo 5 + 1 = 2, Y = (4 + 0) modulo 5 + 1 = 5. Hence the state will be 0 2 5 8 11 after this query.
After the second changing query "c 2 3 5 10", the state will be 0 2 10 23 11 for similar reason.
In the next question query, the actual numbers are X = (1 + 0) modulo 5 + 1 = 2, Y = (3 + 0) modulo 5 + 1 = 4. Hence the answer must be 2 + 10 + 23 = 35.
In the first rollback query "l 1", the actual number is X = (1 + 35) modulo (2 + 1) = 36 modulo 3 = 0, since lastans = 36. Thus the state will be rollbacked to 0 0 0 0 0.
Then the answer of the next question query "q 1 3" must be 0, because all integers are currently 0.
In the second rollback query "l 1", the actual number is X = (1 + 0) modulo (2 + 1) = 1, since lastans = 0. Thus the state will be 0 2 5 8 11, which is the state after the firstchanging query.
Then the answer of the last question query must be 2 + 5 + 8 = 15.
题意:
一棵树,3个操作:
树上两点之间加一个等差数列,
查询树上两点之间权值和,
回到某次修改之后的状态
思路:树链剖分+主席树
#include<cstdio> #include<algorithm> #define N 100001 using namespace std; int root[N],lc[N*300],rc[N*300]; int fa[N],deep[N],bl[N],son[N],id[N],cnt; long long k[N*300],b[N*300],sum[N*300]; int front[N],nxt[N*2],to[N*2],tot; long long A,B,QA,QB,ans; int QL,QR; int sum_chan,now,n,m; int read() { int x=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x; } struct TREE { long long get_sum(long long kk,long long bb,int n) { return (bb+bb+kk*(n-1))*n/2; } void change(int y,int &x,int l,int r) { x=++tot; lc[x]=lc[y]; rc[x]=rc[y]; k[x]=k[y]; b[x]=b[y]; sum[x]=sum[y]; if(l>=QL&&r<=QR) { sum[x]+=get_sum(QB,(l-QL)*QB+QA,r-l+1); k[x]+=QB; b[x]+=(l-QL)*QB+QA; return; } int ll=max(QL,l),rr=min(QR,r); sum[x]+=get_sum(QB,QA+QB*(ll-QL),rr-ll+1); int mid=l+r>>1; if(QL<=mid) change(lc[y],lc[x],l,mid); if(QR>mid) change(rc[y],rc[x],mid+1,r); } void query(int x,int l,int r) { if(!x) return; if(QL<=l&&QR>=r) { ans+=sum[x]; return; } int ll=max(l,QL),rr=min(r,QR); ans+=get_sum(k[x],b[x]+k[x]*(ll-l),rr-ll+1); int mid=l+r>>1; if(QL<=mid) query(lc[x],l,mid); if(QR>mid) query(rc[x],mid+1,r); } }Tree; struct CHAIN { void add(int u,int v) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; } void dfs1(int x,int f) { son[x]++; for(int i=front[x];i;i=nxt[i]) if(to[i]!=f) { fa[to[i]]=x; deep[to[i]]=deep[x]+1; dfs1(to[i],x); son[x]+=son[to[i]]; } } void dfs2(int x,int top) { id[x]=++cnt; bl[x]=top; int y=0; for(int i=front[x];i;i=nxt[i]) if(to[i]!=fa[x]&&son[to[i]]>son[y]) y=to[i]; if(!y) return; dfs2(y,top); for(int i=front[x];i;i=nxt[i]) if(to[i]!=fa[x]&&to[i]!=y) dfs2(to[i],to[i]); } int LCA(int x,int y) { while(bl[x]!=bl[y]) { if(deep[bl[x]]<deep[bl[y]]) swap(x,y); x=fa[bl[x]]; } if(deep[x]>deep[y]) return y; return x; } void change(int x,int y,int dis) { int l=0,r=dis; while(bl[x]!=bl[y]) { if(deep[bl[x]]>deep[bl[y]]) { QL=id[bl[x]]; QR=id[x]; QA=A+(l+QR-QL)*B; QB=-B; Tree.change(root[sum_chan],root[sum_chan],1,n); x=fa[bl[x]]; l+=QR-QL+1; } else { QL=id[bl[y]]; QR=id[y]; QA=A+(r-(QR-QL))*B; QB=B; Tree.change(root[sum_chan],root[sum_chan],1,n); y=fa[bl[y]]; r-=QR-QL+1; } } if(deep[x]<deep[y]) { QL=id[x]; QR=id[y]; QA=A+l*B; QB=B; Tree.change(root[sum_chan],root[sum_chan],1,n); } else { QL=id[y]; QR=id[x]; QA=A+r*B; QB=-B; Tree.change(root[sum_chan],root[sum_chan],1,n); } } void query(int x,int y) { while(bl[x]!=bl[y]) { if(deep[bl[x]]<deep[bl[y]]) swap(x,y); QL=id[bl[x]]; QR=id[x]; Tree.query(root[now],1,n); x=fa[bl[x]]; } if(deep[x]>deep[y]) swap(x,y); QL=id[x]; QR=id[y]; Tree.query(root[now],1,n); } }Chain; int main() { /*freopen("data.txt","r",stdin); freopen("my.txt","w",stdout);*/ n=read(); m=read(); int u,v; for(int i=1;i<n;i++) { scanf("%d%d",&u,&v); Chain.add(u,v); } Chain.dfs1(1,0); Chain.dfs2(1,1); tot=0; char ch[3]; int dis; while(m--) { scanf("%s",ch); if(ch[0]=='c') { root[++sum_chan]=root[now]; u=read(); v=read(); A=read(); B=read(); u=(u+ans)%n+1; v=(v+ans)%n+1; dis=deep[u]+deep[v]-2*deep[Chain.LCA(u,v)]; Chain.change(u,v,dis); now=sum_chan; } else if(ch[0]=='q') { u=read(); v=read(); u=(u+ans)%n+1; v=(v+ans)%n+1; ans=0; Chain.query(u,v); printf("%lld ",ans); } else { u=read(); u=(u+ans)%(sum_chan+1); now=u; } } }