• Peaks


    很好我心态崩了。
    ————————————————
    这里给出两种做法,代码上都有一些问题,建议不要(copy).
    一:离线做法
    考虑直接线段树合并,把问题按边权排。
    做完了。

    离线做法
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    #define M 2000003
    #define N 100003
    
    ll head[N];
    ll n,m;
    
    ll v[M],ls[M],rs[M],fa[N],cnt,t[M];
    
    inline void up(ll now){v[now] = v[ls[now]] + v[rs[now]];}
    
    inline ll get(ll now){return now == fa[now] ? now : fa[now] = get(fa[now]);}
    
    #define mid ((l + r) >> 1)
    
    ll tag;
    
    inline int build(int l,int r,int to){
    	int now = ++cnt;
    //	std::cout<<now<<" "<<l<<" "<<r<<std::endl;
    	if(l == r){
    		t[now] = tag;
    		v[now] = 1;
    		return now;
    	}
    	if(to <= mid)
    	ls[now] = build(l,mid,to);
    	else
    	rs[now] = build(mid + 1,r,to);
    	up(now);
    	return now;
    }
    
    inline int merge(ll a,ll b,ll l,ll r){
    //	std::cout<<a<<" "<<b<<" "<<l<<" "<<r<<std::endl;
    	if(!a || !b)
    	return a + b;
    	if(l == r){
    		v[a] += v[b];
    		return a;
    	}
    	ls[a] = merge(ls[a],ls[b],l,mid);
    	rs[a] = merge(rs[a],rs[b],mid + 1,r);
    	up(a);
    	return a;
    }
    
    inline int Q(ll now,ll q,ll l,ll r){
    //	std::cout<<now<<" "<<q<<" "<<l<<" "<<r<<" "<<v[now]<<" "<<std::endl;
    	if(l == 1 && r == n && q > v[now])
    	return -1;
    	if(l == r)
    	return t[now];
    	if(v[rs[now]] >= q)
    	return Q(rs[now],q,mid + 1,r);
    	else
    	return Q(ls[now],q - v[rs[now]],l,mid);
    }
    
    inline void dfs(ll now,ll l,ll r){
    	if(now){
    //		std::cout<<now<<" "<<l<<" "<<r<<" "<<v[now]<<std::endl;
    		dfs(ls[now],l,mid);
    		dfs(rs[now],mid + 1,r);
    	}
    }
    
    struct P{int to,s,v;}e[N << 4];
    
    inline bool operator < (P a,P b){return a.v < b.v;}
    
    struct Qp{int v,x,k,id;}Qi[N * 5];
    
    ll ans[N * 5];
    
    inline bool operator < (Qp a,Qp b){return a.x < b.x;}
    
    ll q,num[N],b[N],s;
    
    int main(){
    	scanf("%lld%lld",&n,&m);
    	scanf("%lld",&q);	
    	for(int i = 1;i <= n;++i)
    	fa[i] = i;
    	for(int i = 1;i <= n;++i)
    	scanf("%lld",&num[i]),b[++b[0]] = num[i];
    	std::sort(b + 1,b + n + 1);
    	s = std::unique(b + 1,b + n + 1) - b - 1;
    	for(int i = 1;i <= n;++i){
    		ll x = std::lower_bound(b + 1,b + s + 1,num[i]) - b;
    		tag = i;
    		head[i] = build(1,n,x);
    	}
    	for(int i = 1;i <= m;++i)
    		scanf("%d%d%d",&e[i].s,&e[i].to,&e[i].v);
    	std::sort(e + 1,e + m + 1);		
    //	for(int i = 1;i <= m;++i)
    //		std::cout<<e[i].s<<" "<<e[i].to<<" "<<e[i].v<<std::endl;		
    	for(int i = 1;i <= q;++i){
    		Qi[i].id = i;
    		scanf("%d%d%d",&Qi[i].v,&Qi[i].x,&Qi[i].k);
    	}
    	std::sort(Qi + 1,Qi + q + 1);
    //	for(int i = 1;i <= q;++i)
    //	std::cout<<Qi[i].v<<" "<<Qi[i].x<<" "<<Qi[i].k<<std::endl;
    	ll now = 1;
    	for(int i = 1;i <= q;++i){
    //		std::cout<<Qi[i].v<<" "<<Qi[i].x<<" "<<Qi[i].k<<std::endl<<std::endl;
    		while(e[now].v <= Qi[i].x && now <= m){
    //			std::cout<<e[now].s<<" "<<e[now].to<<" "<<e[now].v<<std::endl;
    //			std::cout<<now<<std::endl;
    			ll x = e[now].s,y = e[now].to;
    			ll fx = get(x),fy = get(y);
    			if(fx != fy){
    //			std::cout<<fx<<" "<<fy<<" "<<head[fx]<<" "<<head[fy]<<std::endl;			
    			fa[fx] = fy;
    			head[fy] = merge(head[fx],head[fy],1,n);
    			}	
    			++now;
    		}
    //		puts("");
    		ll fx = get(Qi[i].v);
    //		std::cout<<Q(head[fx],Qi[i].k,1,n)<<std::endl;
    		ll an = Q(head[fx],Qi[i].k,1,n);
    		if(an != -1)
    		ans[Qi[i].id] = num[an];
    		else
    		ans[Qi[i].id] = -1;	
    	}  
    	for(int i = 1;i <= q;++i)
    	std::cout<<ans[i]<<std::endl;
    }
    

    二:在线做法
    考虑重构树,那么在一个权值为(k)的方点下的原点均可以小于等于(k)的边走到。
    倍增+主席树做完了。
    (莫名(RE)心态没了)

    在线做法
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll int
    #define N 200005
    
    ll n,m,q,num[N],b[N];
    
    struct Map{int to,s,v;}e[N];
    
    inline bool operator < (Map a,Map b){return a.v < b.v;}
    
    //________________________//map
    
    ll head[N << 1],v[N << 2],cnt;
    
    struct T{int to,next;}t[N * 6];
    
    inline void add(int x,int y){
    //	std::cout<<x<<" "<<y<<std::endl;
    	t[++cnt].to = y;
    	t[cnt].next = head[x];
    	head[x] = cnt;
    }
    
    ll l[N << 1],r[N << 1],tnum[N],dfncnt,fi[N << 1][25];
    
    inline void dfs(int u,int f){
    	if(u == 0 || u == f)
    	return ;
    //	std::cout<<u<<" "<<v[u]<<std::endl;
    	fi[u][0] = f;
    	for(int i = 1;i <= 19;++i)
    	fi[u][i] = fi[fi[u][i - 1]][i - 1];
    	l[u] = dfncnt;
    	if(head[u] == 0){
    		tnum[++dfncnt] = std::lower_bound(b + 1,b + b[0] + 1,num[u]) - b;
    		r[u] = dfncnt;
    		return ;
    	}
    	for(int i = head[u];i;i = t[i].next){
    		int v = t[i].to;
    		if(v == f)
    		continue;
    		dfs(v,u);
    	}
    	r[u] = dfncnt;
    }
    
    //________________________//tree
    
    ll fa[N];
    
    inline ll find(int x){return (x == fa[x]) ? x : fa[x] = find(fa[x]);}
    
    //________________________//dsu
    
    int tcnt;
    
    int thead[N];
    
    #define mid ((l + r) >> 1)
    
    struct Seg{int l,r,s;Seg(){l = r = s = 0;};}Tr[N * 40];
    
    #define l(x) Tr[x].l
    #define r(x) Tr[x].r
    #define v(x) Tr[x].s
    
    //tnum[M]
    
    
    inline void change(int &now,int pre,int l,int r,int to){
    	if(!now)now = ++ tcnt ;
    //	std::cout<<now<<" "<<pre<<" "<<l<<" "<<r<<" "<<to<<std::endl;	
    	v(now) = v(pre) + 1;
    	if(l == r)return;
    	if(to > mid){l(now) = l(pre),change(r(now),r(pre),mid + 1,r,to);}
    	else{r(now) = r(pre),change(l(now),l(pre),l,mid,to);}
    }
    
    inline void build(){
    	for(int i = 1;i <= n;++i)
    	change(thead[i],thead[i - 1],1,n,tnum[i]);
    }
    inline ll grt(int u,ll x){
    	for(int i = 19;i >= 0;--i){
    		if(v[fi[u][i]] <= x)
    		u = fi[u][i];
    	}
    	return u;
    }
    
    inline ll Q(int lnow,int rnow,int l,int r,int k){
    	int rk = v(r(rnow)) - v(r(lnow));
    //	std::cout<<lnow<<" "<<rnow<<" "<<l<<" "<<r<<" "<<k<<std::endl;
    	if(l == r){
    		if(k - (v(rnow) - v(lnow)) == 0)
    		return l;
    		else
    		return 0;
    	}
    	if(rk >= k)
    	return Q(r(lnow),r(rnow),mid + 1,r,k);
    	else
    	return Q(l(lnow),l(rnow),l,mid,k - rk);
    }
    
    //______________________//Seg tree
    
    ll tot;
    
    inline void kruskal(){
    	ll bcnt = 0;
    	tot = n;
    	for(int i = 1;i <= m && bcnt < n - 1;++i){
    		ll x = e[i].s,y = e[i].to;
    		ll fx = find(x),fy = find(y);
    		if(fx != fy){
    //			std::cout<<e[i].s<<" "<<e[i].to<<" "<<e[i].v<<" "<<fx<<" "<<fy<<std::endl;
    			v[++tot] = e[i].v;
    			add(tot,fx);
    			add(tot,fy);
    			fa[tot] = fa[fx] = fa[fy] = tot;
    			bcnt ++ ;
    		}
    	}
    }
    
    //_______________________//rebuild;
    
    int main(){
    //	freopen("q.in","r",stdin);
    //	freopen("q.ans","w",stdout);	
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i = 1;i <= n;++i)
    	scanf("%d",&num[i]),b[++b[0]] = num[i];
    	std::sort(b + 1,b + b[0] + 1);
    	b[0] = std::unique(b + 1,b + b[0] + 1) - b - 1;
    	for(int i = 1;i <= m;++i){scanf("%d%d%d",&e[i].s,&e[i].to,&e[i].v);}
    	std::sort(e + 1,e + m + 1);
    	for(int i = 1;i <= n;++i)
    	fa[i] = i;
    //	puts("");
    	kruskal();
    	dfs(find(1),0);
    	build();
    	b[0] = -1;
    	v[0] = 1e9 + 7;
    	for(int i = 1;i <= q;++i){
    		ll v,x,k;
    		scanf("%d%d%d",&v,&x,&k);
    		ll rt = grt(v,x);
    //		std::cout<<rt<<std::endl;
    		std::cout<<b[Q(thead[l[rt]],thead[r[rt]],1,n,k)]<<std::endl;
    	}
    }
    
    /*
    7 7 70
    11493 8611 10935 23931 3939 16004 14404 
    3 7 727057
    3 2 860811
    3 1 739841
    3 5 123028
    6 1 501761
    2 6 119601
    3 4 760129
    4 372996 1
    */
    

    建议重构树的题目能离线做还是离线做吧,很难调。

  • 相关阅读:
    codevs 2149 矩形周长
    codevs 3044 矩形面积求并
    codevs 1293 送给圣诞夜的极光
    codevs 2806 红与黑
    codevs 1536 海战
    codevs 1262 不要把球传我
    codevs 2606 约数和问题
    BZOJ 2301 problem b
    BZOJ 3994 约数个数和
    codevs 1173 最优贸易
  • 原文地址:https://www.cnblogs.com/dixiao/p/14791744.html
Copyright © 2020-2023  润新知