• 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;
    }
    
  • 相关阅读:
    arcgis10安装及破解
    11G在用EXP导出时,空表不能导出
    cmd 中键入netstat,net等出现不是内部或外部命令,也不是可运行的程序或批处理文件
    Could not load file or assembly or one of its dependencies. 试图加载格式不正确的程序。
    Spark读写Hbase的二种方式对比
    Handler系列之原理分析
    虚拟目录webconfig的配置
    Smarty的基本使用与总结
    浅谈WEB前后端分离
    学习笔记之MVC级联及Ajax操作
  • 原文地址:https://www.cnblogs.com/mmlz/p/6545701.html
Copyright © 2020-2023  润新知