zoukankan      html  css  js  c++  java
  • BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]

    3545: [ONTAK2010]Peaks

    题意:带权图,多组询问与一个点通过边权(le x)的边连通的点中点权k大值


    又读错题了,输出点一直WA,问的是点权啊

    本题加强版强制在线了,那这道题肯定离线啊,边权从小到大加边不就是煞笔提吗

    奇怪的是合并的时候先序遍历才行...中序和后序都T了

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    #define lc t[x].ch[0]
    #define rc t[x].ch[1]
    #define pa t[x].fa
    const int N=1e5+5, M=5e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n, m, Q, val[N], u, v, w, ans[M];
    struct meow{
    	int u,v,w;
    	bool operator <(const meow &r)const{return w<r.w;}
    }a[M];
    struct qmeow{
    	int u,w,k,id;
    	bool operator <(const qmeow &r)const{return w<r.w;}
    }q[M];
    int fa[N];
    int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
    
    struct SplayTree{
    	struct meow{int ch[2], fa, v, size, w;}t[N];
    	int sz, root;
    	inline void ini() {
    		for(int i=1; i<=n; i++) t[i].size=t[i].w=1, t[i].v=val[i];
    	}
    	inline int wh(int x) {return t[pa].ch[1]==x;}
    	inline void update(int x) {t[x].size=t[lc].size+t[rc].size+t[x].w;}
    	inline void rotate(int x) {
    		int f=t[x].fa, g=t[f].fa, c=wh(x);
    		if(g) t[g].ch[wh(f)]=x; t[x].fa=g;
    		t[f].ch[c]=t[x].ch[c^1]; t[t[f].ch[c]].fa=f;
    		t[x].ch[c^1]=f; t[f].fa=x;
    		update(f); update(x);
    	}
    	inline void splay(int x, int tar) {
    		for(; pa!=tar; rotate(x))
    			if(t[pa].fa != tar) rotate(wh(x)==wh(pa) ? pa : x);
    		if(tar==0) root=x;
    	}
    	void insert(int p) { 
    		int x=root, f=0, v=t[p].v; //printf("insert %d  root %d
    ",p,x);
    		while(x) {
    			if(t[x].v == v) {t[x].w++; t[x].size++; splay(x, 0); return;}
    			f=x;
    			x = v<t[x].v ? lc : rc;
    		}
    		x=p;
    		t[f].ch[ v>t[f].v ]=x; t[x].fa=f; //printf("f %d %d
    ",f,x);
    		splay(x, 0);  //see(x);
    	}
    	void order(int x) {
    		int l=lc, r=rc; 
    		lc=rc=pa=0; t[x].size=t[x].w;
    		if(l) order(l);
    		if(r) order(r);
    		insert(x);
    	}
    	void Merge(int x, int y) {
    		if(x==y) return; //printf("Merge %d %d
    ",x,y);
    		splay(x, 0); splay(y, 0);
    		if(t[x].size > t[y].size) swap(x, y);
    		fa[x]=y; root=y;
    		order(x);
    	}
    	int kth(int x, int k) {
    		splay(x, 0); int lsize=0;  //printf("kth %d %d  %d
    ",x,k,t[x].size);
    		if(k>t[x].size) return -1;
    		k=t[x].size-k+1; 
    		while(x) {
    			int _=lsize+t[lc].size;
    			if(k<=_) x=lc;
    			else if(k<=_+t[x].w) return t[x].v;
    			else lsize=_+t[x].w, x=rc;
    		}
    		return -1;
    	}
    }S;
    
    int main() {
    	freopen("in","r",stdin);
    	n=read(); m=read(); Q=read();
    	for(int i=1; i<=n; i++) val[i]=read(), fa[i]=i;
    	S.ini();
    	for(int i=1; i<=m; i++) u=read(),v=read(),w=read(),a[i]=(meow){u,v,w};
    	for(int i=1; i<=Q; i++) u=read(),v=read(),w=read(),q[i]=(qmeow){u,v,w,i};
    
    	sort(a+1,a+1+m); sort(q+1, q+1+Q);
    	int now=1;
    	for(int i=1; i<=Q; i++) {
    		int w=q[i].w;
    		while(now<=m && a[now].w<=w) S.Merge(find(a[now].u), find(a[now].v)), now++;
    		ans[q[i].id] = S.kth(find(q[i].u), q[i].k);
    	}
    	for(int i=1; i<=Q; i++) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    WORD窗体保护密码清除
    在Fedora 23 Server和Workstation上安装LAMP(Linux, Apache, MariaDB和PHP)
    firefox 提示 ssl_error_unsupported_version 的解决方法
    算法题:求一个序列S中所有包含T的子序列(distinct sub sequence)
    Django模板输出Dict所有Value的效率问题
    笔记:LNK2001不代表链接器真的需要链接相关符号
    Windows Restart Manager 重启管理器
    advapi32.dll kernel32.dll 中的两套注册表API
    使用GDI+保存带Alpha通道的图像(续)
    使用GDI+保存带Alpha通道的图像
  • 原文地址:https://www.cnblogs.com/candy99/p/6621907.html
Copyright © 2011-2022 走看看