• [BZOJ3551]Peaks加强版


    题目大意:见https://www.cnblogs.com/Mrsrz/p/9354136.html

    强制在线

    解题思路:
    Kruskal重构树。
    我们从小到大加入边,每次合并两个连通块时,新建一个节点作为它们的父亲,点权为原来的边权。
    然后对于每个询问,倍增找最上方的点权不超过x的点,则该点构成的子树上的所有叶子节点就是原来的点能到的所有节点。
    于是对每棵子树建主席树,查询时就是在子树内查询第k大。建主席树时相当于线段树合并。
    C++ Code:

    #include<bits/stdc++.h>
    #define N 100005
    template<typename T>
    inline void read(T&d){
    	d=0;static int c;
    	for(c=getchar();!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    }
    struct edge{
    	int u,v,dis;
    	inline bool operator<(const edge&rhs)const{return dis<rhs.dis;}
    }E[N*5];
    struct Edge{
    	int to,nxt;
    }e[N<<3];
    struct segmentTreeNode{
    	int s,ls,rs;
    }d[6000005];
    int n,m,q,h[N],fa[N<<1],nodes,f[N<<1][19],cnt=0,dang[N<<1],head[N<<1],hh[N],rt[N<<1];
    int treenode=0;
    inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    void init(int l,int r,int&o,int p){
    	o=++treenode;
    	d[o].s=1;
    	if(l==r)return;
    	int mid=l+r>>1;
    	if(p<=mid)init(l,mid,d[o].ls,p);else
    	init(mid+1,r,d[o].rs,p);
    }
    int merge(int ls,int rs){
    	if(!ls||!rs)return ls|rs;
    	int nw=++treenode;
    	if(!d[ls].ls&&!d[ls].rs){
    		d[nw].s=d[ls].s+d[rs].s;
    		return nw;
    	}
    	d[nw].ls=merge(d[ls].ls,d[rs].ls);
    	d[nw].rs=merge(d[ls].rs,d[rs].rs);
    	d[nw].s=d[d[nw].ls].s+d[d[nw].rs].s;
    	return nw;
    }
    void dfs(int now){
    	for(int i=head[now];i;i=e[i].nxt){
    		dfs(e[i].to);
    		if(!rt[now])rt[now]=rt[e[i].to];else
    		rt[now]=merge(rt[now],rt[e[i].to]);
    	}
    	if(!head[now])
    	init(0,N,rt[now],hh[now]);
    }
    int query(int l,int r,int&o,int k){
    	if(l==r)return l;
    	int mid=l+r>>1;
    	if(d[d[o].rs].s>=k)return query(mid+1,r,d[o].rs,k);
    	return query(l,mid,d[o].ls,k-d[d[o].rs].s);
    }
    int main(){
    	read(n),read(m),read(q);
    	for(int i=1;i<=n;++i)read(h[i]),hh[i]=h[i];
    	std::sort(h+1,h+n+1);
    	int nn=std::unique(h+1,h+n+1)-h-1;
    	for(int i=1;i<=n;++i)hh[i]=std::lower_bound(h+1,h+nn+1,hh[i])-h;
    	for(int i=1;i<=m;++i)read(E[i].u),read(E[i].v),read(E[i].dis);
    	std::sort(E+1,E+m+1);
    	for(int i=1;i<=n;++i)fa[i]=i,fa[i+n]=i+n;
    	nodes=n;
    	for(int less_node=n-1,i=1;less_node&&i<=m;++i){
    		int x=find(E[i].u),y=find(E[i].v);
    		if(x!=y){
    			fa[x]=fa[y]=f[x][0]=f[y][0]=++nodes;
    			dang[nodes]=E[i].dis;
    			--less_node;
    			e[++cnt]=(Edge){x,head[nodes]};
    			head[nodes]=cnt;
    			e[++cnt]=(Edge){y,head[nodes]};
    			head[nodes]=cnt;
    		}
    	}
    	dang[0]=0x3f3f3f3f;
    	memset(d,0,sizeof d);
    	dfs(nodes);
    	for(int j=1;j<19;++j)
    	for(int i=1;i<=nodes;++i)
    	f[i][j]=f[f[i][j-1]][j-1];
    	int ans=0;
    	while(q--){
    		int u,x,k;
    		read(u),read(x),read(k);
    		u^=ans,x^=ans,k^=ans;
    		for(int i=18;~i;--i)if(dang[f[u][i]]<=x)u=f[u][i];
    		if(d[rt[u]].s<k)puts("-1"),ans=0;else
    		printf("%d
    ",ans=h[query(0,N,rt[u],k)]);
    	}
    	return 0;
    }

     

  • 相关阅读:
    识别IE11浏览器
    国庆过后老革命
    有些东西再忙也要做
    云计算
    SVN下Update出现代码文件删除状态问题
    如何避免历史回退到登录页面
    CodeSmith连Oracle
    NHibernate直接执行SQL进行插入
    nhibernate实体类主键ID赋值问题
    NHibernate不支持复杂的linq,就一定要用DataTable这么低级吗
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/9355698.html
Copyright © 2020-2023  润新知