zoukankan      html  css  js  c++  java
  • CF763E Timofey and our friends animals

    题目戳这里

    首先题解给的是并查集的做法。这个做法很好想,但是很难码。用线段树数来维护并查集,暴力合并。

    这里推荐另一个做法,可以无视(K)的限制。我们给每条边加个边权,这个边权为这条边左端点的值。然后我们将询问离线,按(r),从小到大处理。

    对于当前询问([l,r])我们用lct维护所有右端点(le r)的边构成的最大生成树,然后用树状数组查询生成树中边权(ge l)的边有几条即可。

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstdlib>
    using namespace std;
    
    #define lowbit(a) (a&-a)
    const int maxn = 200010,maxm = 500010;
    int N,K,M,tot,cnt,tree[maxn],Q; bool rev[maxn];
    int ch[maxn][2],fa[maxn],ma[maxn],pma[maxn],key[maxn],stack[maxn],ans[maxn];
    queue <int> team;
    
    inline void ins(int a,int b) { for (;a <= N;a += lowbit(a)) tree[a] += b; }
    inline int calc(int a) { int ret = 0; for (;a;a -= lowbit(a)) ret += tree[a]; return ret; }
    
    inline int gi()
    {
    	int ret = 0,f = 1; char ch;
    	do ch = getchar(); while (!(ch >= '0'&&ch <= '9')&&ch != '-');
    	if (ch == '-') f = -1;
    	do ret = ret*10+ch-'0',ch = getchar(); while (ch >= '0'&&ch <= '9');
    	return ret*f;
    }
    
    struct Node
    {
    	int l,r,id;
    	inline void read(int i) { l = gi(),r = gi(),id = i; }
    	friend inline bool operator <(const Node &a,const Node &b) { return a.r < b.r; }
    }query[maxn];
    struct EDGE
    {
    	int u,v;
    	inline void read() { u = gi(),v = gi(); if (u > v) swap(u,v); }
    	friend inline bool operator <(const EDGE &a,const EDGE &b) { return a.v < b.v; }
    }edge[maxm];
    
    inline bool isroot(int x) { return ch[fa[x]][0] != x&&ch[fa[x]][1] != x; }
    inline void update(int x)
    {
    	int lc = ch[x][0],rc = ch[x][1];
    	ma[x] = key[x]; pma[x] = x;
    	if (lc && ma[lc] < ma[x]) ma[x] = ma[lc],pma[x] = pma[lc];
    	if (rc && ma[rc] < ma[x]) ma[x] = ma[rc],pma[x] = pma[rc];
    }
    inline int newnode(int w)
    {
    	int ret;
    	if (team.empty()) ret = ++cnt; else ret = team.front(),team.pop();
    	key[ret] = w; fa[ret] = ch[ret][0] = ch[ret][1] = 0;
    	update(ret); return ret;
    }
    inline void rotate(int x)
    {
    	int y = fa[x],z = fa[y],l = ch[y][1] == x,r = l^1;
    	if (!isroot(y)) ch[z][ch[z][1] == y] = x; fa[x] = z;
    	if (ch[x][r]) fa[ch[x][r]] = y; ch[y][l] = ch[x][r];
    	fa[y] = x; ch[x][r] = y; update(y); update(x);
    }
    inline void pushdown(int x)
    {
    	if (rev[x])
    	{
    		int lc = ch[x][0],rc = ch[x][1];
    		rev[x] = false; swap(ch[x][0],ch[x][1]);
    		if (lc) rev[lc] ^= 1; if (rc) rev[rc] ^= 1;
    	}
    }
    inline void splay(int x)
    {
    	int top = 0,i;
    	for (i = x;!isroot(i);i = fa[i]) stack[++top] = i; stack[++top] = i;
    	while (top) pushdown(stack[top--]);
    	while (!isroot(x))
    	{
    		int y = fa[x],z = fa[y];
    		if (!isroot(y))
    		{
    			if ((ch[y][0] == x)^(ch[z][0] == y)) rotate(x);
    			else rotate(y);
    		}
    		rotate(x);
    	}
    }
    inline int access(int x) { int t = 0; for (;x;t = x,x = fa[x]) splay(x),ch[x][1] = t,update(x); return t; }
    inline int evert(int x) { int t = access(x); rev[t] ^= 1; return t; }
    inline int find(int x) { int t = access(x); while (pushdown(t),ch[t][0]) t = ch[t][0]; return t; }
    inline void cut(int now)
    {
    	evert(now); team.push(now); ins(edge[key[now]].u,-1);
    	access(edge[key[now]].u); splay(now); ch[now][1] = fa[edge[key[now]].u] = 0;
    	access(edge[key[now]].v); splay(now); ch[now][1] = fa[edge[key[now]].v] = 0;
    }
    inline void link(int w)
    {
    	if (find(edge[w].u) == find(edge[w].v))
    		evert(edge[w].u),cut(pma[access(edge[w].v)]);
    	int now = newnode(w);
    	int t1 = evert(edge[w].u),t2 = evert(edge[w].v);
    	fa[t1] = fa[t2] = now; ins(edge[w].u,1);
    }
    
    int main()
    {
    	freopen("763E.in","r",stdin);
    	freopen("763E.out","w",stdout);
    	cnt = N = gi(); K = gi(); M = gi();
    	for (int i = 1;i <= M;++i) edge[i].read();
    	for (int i = 1;i <= N;++i) key[i] = 1<<30,update(i);
    	sort(edge+1,edge+M+1);
    	Q = gi();
    	for (int i = 1;i <= Q;++i) query[i].read(i);
    	sort(query+1,query+Q+1);
    	for (int i = 1,now = 1;i <= Q;++i)
    	{
    		for (;now <= M&&edge[now].v <= query[i].r;) link(now++);
    		ans[query[i].id] = query[i].r-query[i].l+1-(calc(query[i].r)-calc(query[i].l-1));
    	}
    	for (int i = 1;i <= Q;++i) printf("%d
    ",ans[i]);
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    HDU 1124 Factorial
    hdu 1690 Bus System
    hdu 1113 Word Amalgamation
    POJ 2482 Stars in Your Window
    hdu 1385 ZOJ 1456 Minimum Transport Cost(经典floyd)
    hdu 1907 John
    VMware 虚拟机 安装 UBuntu 9.10 命令模式转换成窗口模试
    #pragma CODE_SEG __NEAR_SEG NON_BANKED详解
    Ubuntu 下Hadoop 伪分布式 hadoop0.20.2.tar.gz 的安装
    文件拷贝代码以及疑问
  • 原文地址:https://www.cnblogs.com/mmlz/p/6545701.html
Copyright © 2011-2022 走看看