【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)

54  种草
约翰有 N 个牧场,编号为 1 到 N。它们之间有 N 1 条道路,每条道路连接两个牧场。通过这
些道路,所有牧场都是连通的。
刚开始的时候,所有道路都是光秃秃的,没有青草。约翰会在一些道路上批量种草。每次开始种
草的时候,约翰会选择一个牧场作为起点,一个牧场作为终点,找到从起点到终点的最短路径,在这
条路径上所有的道路上分别种下一棵新的青草。
贝西在监督约翰的工作,她迫不及待地想知道每条道路上已经有多少青草了。约翰的工作总是被
贝西打断,他不胜其烦,所以请你来帮忙回答贝西的问题。约翰的工作和贝西的询问是穿插进行的,
输入数据将会依次出现 M 个事件,以字符 P 开头的事件表示约翰在一条路径上种植了青草,以字符
Q 开头的事件表示贝西在查询一条道路上有多少青草。
输入格式
• 第一行:两个整数 N M, 2 N 105 , 1 M 105
• 第二行到第 N 行:第 i + 1 行有两个整数 Ui Vi,表示第 i 条道路连接的两个牧场编号,
1 Ui,Vi N
• 第 N + 1 行到第 N + Q 行:每行首先由一个大写字母:
如果是 P,随后会有两个整数 A B,表示约翰在从 A 通向 B 的每条道路上都新种了一
棵青草, 1 A,B N
如果是 Q,随后会有两个整数 A B,表示贝西查询一条道路上的青草数量, A B
这条道路的两个端点, 1 A,B N,保证输入数据中存在一条 A B 的道路
输出格式
• 对每个查询请求,输出该条道路上青草的数量,以换行符分隔
样例输入
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
样例输出
212

 

【分析】

  因为是树状数组专题,于是我打了树状数组没有打线段树。

  表示人生第一次树状数组的区间修改和区间查询(我太垃圾..

  其实比线段树可还是短多了,就是维护两个东西的前缀和,一个是delta[i],一个是delta[i]*i,delta[i]表示i~n的共同增量。

  具体看我转的那篇东西:http://www.cnblogs.com/Konjakmoyu/p/5981935.html

  然后就是树剖啦ORZ,好多年没打了居然还能打出来ORZ...

 

代码如下:

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<cmath>
  8 using namespace std;
  9 #define Maxn 100010
 10 
 11 struct node
 12 {
 13     int x,y,next;
 14 }t[Maxn*2];int len;
 15 int first[Maxn];
 16 
 17 void ins(int x,int y)
 18 {
 19     t[++len].x=x;t[len].y=y;
 20     t[len].next=first[x];first[x]=len;
 21 }
 22 
 23 char s[10];
 24 
 25 int sm[Maxn],son[Maxn],fa[Maxn],dep[Maxn];
 26 void dfs(int x,int f)
 27 {
 28     sm[x]=1;son[x]=0;fa[x]=f;dep[x]=dep[f]+1;
 29     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
 30     {
 31         int y=t[i].y;
 32         dfs(y,x);
 33         sm[x]+=sm[y];
 34         if(sm[y]>sm[son[x]]) son[x]=y;
 35     }
 36 }
 37 
 38 int tp[Maxn],dfn[Maxn],cnt;
 39 void dfs2(int x,int tpp)
 40 {
 41     if(x==0) return;
 42     dfn[x]=++cnt;tp[x]=tpp;
 43     dfs2(son[x],tpp);
 44     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
 45     {
 46         int y=t[i].y;
 47         if(y==son[x]) continue;
 48         dfs2(y,y);
 49     }
 50 }
 51 
 52 int c1[Maxn],c2[Maxn];
 53 
 54 void ffind(int x,int y,int c)
 55 {
 56     for(int i=x;i<=cnt;i+=i&(-i))
 57         c1[i]+=c,c2[i]+=c*x;
 58     y++;
 59     for(int i=y;i<=cnt;i+=i&(-i))
 60         c1[i]+=-c,c2[i]+=(-c)*y;
 61 }
 62 
 63 int get_ans(int x,int y)
 64 {
 65     int ans=0;
 66     for(int i=y;i>=1;i-=i&(-i))
 67       ans+=(y+1)*c1[i]-c2[i];
 68     x--;
 69     for(int i=x;i>=1;i-=i&(-i))
 70         ans-=(x+1)*c1[i]-c2[i];
 71     return ans;
 72 }
 73 
 74 void change(int x,int y)
 75 {
 76     int tt;
 77     while(tp[x]!=tp[y])
 78     {
 79         if(dep[tp[x]]>dep[tp[y]])
 80         {
 81             tt=x,x=y,y=tt;
 82         }
 83         ffind(dfn[tp[y]],dfn[y],1);
 84         y=fa[tp[y]];
 85     }
 86     if(x==y) return;
 87     if(dep[x]>dep[y]) tt=x,x=y,y=tt;
 88     ffind(dfn[x]+1,dfn[y],1);
 89 }
 90 
 91 int query(int x,int y)
 92 {
 93     int ans=0;
 94     int tt;
 95     while(tp[x]!=tp[y])
 96     {
 97         if(dep[tp[x]]>dep[tp[y]])
 98         {
 99             tt=x,x=y,y=tt;
100         }
101         ans+=get_ans(dfn[tp[y]],dfn[y]);
102         y=fa[tp[y]];
103     }
104     if(x==y) return ans;
105     if(dep[x]>dep[y]) tt=x,x=y,y=tt;
106     ans+=get_ans(dfn[x]+1,dfn[y]);
107     return ans;
108 }
109 
110 int main()
111 {
112     int n,m;
113     scanf("%d%d",&n,&m);
114     len=0;
115     memset(first,0,sizeof(first));
116     for(int i=1;i<n;i++)
117     {
118         int x,y;
119         scanf("%d%d",&x,&y);
120         ins(x,y);ins(y,x);
121     }
122     sm[0]=0;dep[0]=0;
123     dfs(1,0);
124     cnt=0;
125     dfs2(1,1);
126     
127     memset(c1,0,sizeof(c1));
128     memset(c2,0,sizeof(c2));
129     for(int i=1;i<=m;i++)
130     {
131         int x,y;
132         scanf("%s%d%d",s,&x,&y);
133         if(s[0]=='P')
134         {
135             change(x,y);
136         }
137         else
138         {
139             printf("%d\n",query(x,y));
140         }
141     }
142     return 0;
143 }
【SPOJ GRASSPLA】

 

2016-10-28 09:56:44

 

posted @ 2016-10-28 09:46  konjak魔芋  阅读(409)  评论(0编辑  收藏  举报