Codeforces Round #395 (Div. 1) E. Timofey and our friends animals(lct动态维护mst)
来源:互联网 发布:java web入门书籍推荐 编辑:程序博客网 时间:2024/06/08 06:55
After his birthday party, Timofey went to his favorite tree alley in a park. He wants to feed there his favorite birds — crows.
It's widely known that each tree is occupied by a single crow family. The trees in the alley form a row and are numbered from 1 to n. Some families are friends to each other. For some reasons, two families can be friends only if they live not too far from each other, more precisely, there is no more than k - 1 trees between any pair of friend families. Formally, the family on the u-th tree and the family on thev-th tree can be friends only if |u - v| ≤ k holds.
One of the friendship features is that if some family learns that Timofey is feeding crows somewhere, it notifies about this all friend families. Thus, after Timofey starts to feed crows under some tree, all the families that are friends to the family living on this tree, as well as their friends and so on, fly to the feeding place. Of course, the family living on the tree also comes to the feeding place.
Today Timofey came to the alley and noticed that all the families that live on trees with numbers strictly less than l or strictly greater thanr have flown away. Thus, it is not possible to pass the information about feeding through them. Moreover, there is no need to feed them. Help Timofey to learn what is the minimum number of trees under which he has to feed crows so that all the families that have remained will get the information about feeding. You are given several situations, described by integers l and r, you need to calculate the answer for all of them.
The first line contains integers n and k (1 ≤ n ≤ 105, 1 ≤ k ≤ 5), where n is the number of trees, and k is the maximum possible distance between friend families.
The next line contains single integer m (0 ≤ m ≤ n·k) — the number of pair of friend families.
Each of the next m lines contains two integers u and v (1 ≤ u, v ≤ 105), that means that the families on trees u and v are friends. It is guaranteed that u ≠ v and |u - v| ≤ k. All the given pairs are distinct.
The next line contains single integer q (1 ≤ q ≤ 105) — the number of situations you need to calculate the answer in.
Each of the next q lines contains two integers l and r (1 ≤ l ≤ r ≤ 105), that means that in this situation families that have flown away lived on such trees x, so that either x < l or x > r.
Print q lines. Line i should contain single integer — the answer in the i-th situation.
5 331 32 34 551 11 22 31 31 5
12112
In the first example the following family pairs are friends: (1, 3), (2, 3) and (4, 5).
- In the first situation only the first family has remained, so the answer is 1.
- In the second situation the first two families have remained, and they aren't friends, so the answer is 2.
- In the third situation the families 2 and 3 are friends, so it is enough to feed any of them, the answer is 1.
- In the fourth situation we can feed the first family, then the third family will get the information from the first family, and the second family will get the information from the third. The answer is 1.
- In the fifth situation we can feed the first and the fifth families, so the answer is 2.
#include<iostream>#include<string>#include<algorithm>#include<cstdlib>#include<cstdio>#include<set>#include<map>#include<vector>#include<cstring>#include<stack>#include<queue>#define INF 2147483640#define eps 1e-9#define MAXN 0x3f#define N 100005using namespace std;int n,m,k,x,y,q,s[6*N],ch[6*N][2],f[N],Ans[N],value[6*N],Max[6*N],Max_num[6*N],fa[6*N];bool lazy[6*N];struct thing{int x,y,num,val;}ask[N],edg[6*N];vector<int> G_ask[N],G_edg[N];inline bool isroot(int x){return ch[fa[x]][0] != x && ch[fa[x]][1] != x;}void push_up(int x){Max[0] = 0;Max[x] = value[x],Max_num[x] = x;if(Max[x] < Max[ch[x][0]]){Max[x] = Max[ch[x][0]];Max_num[x] = Max_num[ch[x][0]];}if(Max[x] < Max[ch[x][1]]){Max[x] = Max[ch[x][1]];Max_num[x] = Max_num[ch[x][1]];}}void rotate(int x){int y = fa[x],z = fa[y];int d = ch[y][0] == x ? 0 : 1;if(!isroot(y)){if(ch[z][0] == y) ch[z][0] = x;else ch[z][1] = x;}fa[y] = x,fa[x] = z,fa[ch[x][d^1]] = y;ch[y][d] = ch[x][d^1],ch[x][d^1] = y;push_up(y),push_up(x);}inline void push_down(int x){if(!lazy[x]) return;int ls = ch[x][0],rs = ch[x][1];lazy[x]^=1,lazy[ls]^=1;lazy[rs]^=1;swap(ch[ls][0],ch[ls][1]);swap(ch[rs][0],ch[rs][1]);}void splay(int x){int tot = 0;s[++tot] = x;for(int i = x;!isroot(i);i = fa[i]) s[++tot] = fa[i];for(;tot;tot--) push_down(s[tot]);while(!isroot(x)){int y = fa[x],z = fa[y];if(!isroot(y)){if((ch[z][0] == y) ^ (ch[y][0] == x)) rotate(x);else rotate(y);}rotate(x);}}void access(int x){int t = 0;while(x){splay(x);ch[x][1] = t; //parent path 边中儿子一定是子链root,父亲是子链root实际父亲 push_up(x);t = x,x = fa[x];}}int findroot(int x){splay(x);while(ch[x][0]) x = ch[x][0];return x;}void makeroot(int x) //x变成根 {access(x),splay(x);swap(ch[x][0],ch[x][1]);lazy[x]^=1; }void link(int x,int y){makeroot(x);fa[x] = y;}void cut(int x,int y) //一次一条边 {makeroot(x),access(y),splay(y),ch[y][0] = fa[x] = 0;push_up(y);}bool islink(int x,int y){makeroot(x);access(y);return findroot(y) == x;}int lowbit(int x){return x & (-x);}void Insert(int x,int k){while(x <= n){f[x] += k;x += lowbit(x);}}int Find_sum(int x){int ans = 0;while(x){ans += f[x];x -= lowbit(x);}return ans;}int main(){memset(Max,0,sizeof(Max));memset(value,0,sizeof(value));scanf("%d%d",&n,&k);scanf("%d",&m);for(int i = 1;i <= m;i++){scanf("%d%d",&edg[i].x,&edg[i].y);if(edg[i].x > edg[i].y) swap(edg[i].x,edg[i].y); edg[i].val = edg[i].y;Max[i + n] = value[i + n] = edg[i].val;Max_num[i + n] = i + n;G_edg[edg[i].x].push_back(i);}scanf("%d",&q);for(int i = 1;i <= q;i++){scanf("%d%d",&ask[i].x,&ask[i].y);G_ask[ask[i].x].push_back(i);}for(int i = n;i;i--){for(int j = 0;j < G_edg[i].size();j++){int e = G_edg[i][j];int x = edg[e].x,y = edg[e].y,val = edg[e].val;if(islink(x,y)){if(Max[y] > val){int u = edg[Max_num[y] - n].x,v = edg[Max_num[y] - n].y,t = Max_num[y];Insert(Max[y],-1);Insert(val,1);cut(u,t); //删过Max_num[y]就会变 cut(t,v);link(x,n + e);link(n + e,y);}}else {Insert(val,1);link(x,n + e);link(n + e,y);}}for(int j = 0;j < G_ask[i].size();j++) {int v = G_ask[i][j];Ans[v] = ask[v].y - ask[v].x + 1 - Find_sum(ask[v].y);}}for(int i = 1;i <= q;i++) printf("%d\n",Ans[i]);}
- Codeforces Round #395 (Div. 1) E. Timofey and our friends animals(lct动态维护mst)
- Codeforces Round #395 (Div. 2)E: Timofey and remoduling(数学+数论)
- Codeforces Round #395 (Div. 2) C. Timofey and a tree
- Codeforces Round #395 (Div. 2)Timofey and cubes
- Codeforces Round #395 (Div. 2)Timofey and a tree
- Codeforces Round #395 (Div. 2) D. Timofey and rectangles
- Codeforces Round #395 (Div. 2)D. Timofey and rectangles
- Codeforces Round #395(Div. 2)B. Timofey and cubes【模拟】
- Codeforces Round #395 (Div. 2) C. Timofey and a tree
- Codeforces Round #395 (Div. 2) D. Timofey and rectangles
- Codeforces Round #395 (Div. 2) D. Timofey and rectangles
- Codeforces Round #395 (Div. 2) D. Timofey and rectangles_0
- Codeforces Round #395 (Div. 2)-D. Timofey and rectangles
- 【codeforces】Codeforces Round #305 (Div. 1)E. Mike and Friends【后缀数组+线段树】
- 【后缀自动机】Codeforces Round #305 (Div. 1) E. Mike and Friends
- Codeforces Round #305 (Div. 1)E. Mike and Friends 后缀数组+RMQ+线段树
- Codeforces Round #305 (Div. 1)E. Mike and Friends【后缀数组+线段树】
- Codeforces Round #395 (Div. 1) D Timofey and a flat tree (树hash)
- JWebFileTrans- 一款可以从网络上下载文件的小程序(一)
- C11-1 浮点数输出
- 归并排序
- P1540 机器翻译
- 1033. To Fill or Not to Fill (25)-贪心(难)
- Codeforces Round #395 (Div. 1) E. Timofey and our friends animals(lct动态维护mst)
- 共同学习Java源代码-数据结构-HashMap(二)
- SURF算法及源码分析(下)
- 数据库分库分表(sharding)系列(五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案
- mysql数据库跨域访问解决方案(添加mysql帐号方法)
- tomcat7.0.52及以上版本web.xml引用外部文件问题
- 类的带参方法
- Ubuntu系统下挂载新硬盘(1)
- Bzoj 2243: [SDOI2011]染色(树链剖分+线段树)