zoukankan      html  css  js  c++  java
  • [BZOJ 3551+3545]Peaks

    加强:题目传送-BZOJ3551

    原味:题目传送-BZOJ3545

    题意:

    有一个(n)个点(m)条边的无向图,点有点权,边有边权。
    (q)次询问(u,val,k)
    表示从(u)出发,经过的边权都小于等于(val),能到达的所有点中,点权第(k)大的权值
    强制在线
    $n le 100000,m le 500000,q le 300000 $

    题解:

    做过NOI2018D1T1的再做这题就思路清晰了
    你需要先学会Kruskal重构树,也不是什么高大上的东西..
    然后这就变成了一棵树,按DFS序将叶子节点映射到一个序列上
    转换为区间第K大,就随便做了..我用的是主席树

    过程:

    先忘了强制在线,再各种细节..

    代码:

    const int N=100010,M=500010,lgN=18,ALL=N<<1;
    int n,m,q,rt,all;
    int h[N];
    int head[ALL],nxt[ALL],to[ALL],lst=0;
    int bd[ALL],fa[ALL];
    inline void adde(int x,int y) {
    	assert(fa[y]==x);
    	nxt[++lst]=head[x]; to[lst]=y; head[x]=lst;
    }
    namespace KRU {
    	struct EDGE {
    		int x,y,c;
    		inline void in() {
    			read(x); read(y); read(c);
    		}
    		bool operator < (const EDGE &a)const {
    			return c<a.c;
    		}
    	}e[M];
    	int fat[N],ref[N],ind=0;
    	int father(int x) {return x==fat[x] ? x : fat[x]=father(fat[x]);}
    	inline int Kruskal() {
    		sort(e+1,e+m+1); int k=0; ind=n;
    		for(int i=1;i<=n;i++) fat[i]=ref[i]=i;
    		for(int i=1;i<=m;i++) {
    			int fx=father(e[i].x),fy=father(e[i].y);
    			if(fx!=fy) {
    				int np=++ind; fa[ref[fy]]=fa[ref[fx]]=np;
    				adde(np,ref[fy]); adde(np,ref[fx]); bd[np]=e[i].c;
    				ref[fy]=np; ref[fx]=0; fat[fx]=fy;
    				if(++k==n-1) return ind;
    			}
    		}
    		int np=++ind; bd[np]=INF;
    		for(int i=1;i<=n;i++)
    			if(father(i)==i) {
    				fa[ref[i]]=np;
    				adde(np,ref[i]);
    			}
    		// printf("lst=%d
    ",lst);
    		return ind;
    	}
    }
    int le[ALL],t_s[ALL],s_t[ALL],ind=0;
    namespace TREE {
    	int anc[ALL][lgN+2],lim[ALL][lgN+2],dep[ALL],sz[ALL];
    	void Print(int u) {
    		for(int i=1;i<dep[u];i++) putchar('	'); printf("%d:%d %d
    ",u,fa[u],bd[u]);
    		for(int i=head[u];i;i=nxt[i]) Print(to[i]);
    	}
    	int cnt;
    	void Build(int u) {
    		// printf("%d
    ",u);
    		bool fl=0; sz[u]=0; ++cnt;
    		for(int i=head[u];i;i=nxt[i]) {
    			int v=to[i]; assert(v!=fa[u]);
    			dep[v]=dep[u]+1;
    			anc[v][0]=u;
    			lim[v][0]=bd[u];
    			Build(v);
    			if(!fl) le[u]=le[v];
    			sz[u]+=sz[v];
    			fl=1;
    		}
    		if(!fl) assert(u<=n);
    		if(u<=n) assert(!fl);
    		if(!fl) {le[u]=u; t_s[u]=++ind; s_t[ind]=u; sz[u]=1;}
    	}
    	inline void Init(int rt) {
    		lim[rt][0]=INF; dep[rt]=1;//ATT
    		mem(lim,63);
    		Build(rt); assert(cnt==all); assert(ind==n);
    		for(int j=1;j<=lgN;j++)
    			for(int i=1;i<=all;i++) {
    				anc[i][j]=anc[anc[i][j-1]][j-1];
    				lim[i][j]=lim[anc[i][j-1]][j-1];
    			}
    	}
    	inline int Find(int u,int v) {
    		for(int i=lgN;i>=0;i--) if(lim[u][i]<=v) u=anc[u][i];
    		return u;
    	}
    }
    namespace SEG {
    	#define lc ch[u][0]
    	#define rc ch[u][1]
    	#define left lc,l,mid
    	#define right rc,mid+1,r
    	#define mid ((l+r)>>1)
    	const int U=N*lgN;
    	int rt[ALL],sz[U],ch[U][2],ind=1;
    	inline int New_Node(int u) {
    		sz[++ind]=sz[u];
    		ch[ind][0]=ch[u][0]; ch[ind][1]=ch[u][1];
    		return ind;
    	}
    	void Modify(int &u,int l,int r,int x) {
    		// printf("%d %d %d %d
    ",u,l,r,x);
    		u=New_Node(u);
    		if(l==r) {
    			if(l!=x) cerr<<x<<endl;
    			assert(l==x);
    			++sz[u]; return;
    		}
    		if(x<=mid) Modify(left,x);
    		if(x> mid) Modify(right,x);
    		sz[u]=sz[lc]+sz[rc];
    	}
    	int Query(int u1,int u2,int l,int r,int k) {
    		if(l==r) return l;
    		int szl=sz[ch[u2][0]]-sz[ch[u1][0]];
    		// printf("%d %d %d %d %d
    ",u1,u2,szl,l,r);
    		if(szl<k) return Query(ch[u1][1],ch[u2][1],mid+1,r,k-szl);
    		else return Query(ch[u1][0],ch[u2][0],l,mid,k);
    	}
    	inline void Init() {
    		for(int i=1;i<=n;i++) {
    			rt[i]=rt[i-1];
    			// printf("%d
    ",s_t[i]);
    			Modify(rt[i],1,n,h[s_t[i]]);
    			// printf("%d
    ",sz[rt[i]]);
    		}
    		// printf("rt
    "); for(int i=1;i<=n;i++) printf("%d ",rt[i]); puts("");
    	}
    }
    map<int,int> key;
    int _key[N];
    int num[N],tot;
    signed main() {
    	// freopen("4.in","r",stdin);
    	// freopen("my.out","w",stdout);
    	read(n); read(m); read(q); tot=n;
    	for(int i=1;i<=n;i++) read(h[i]),num[i]=h[i];
    	sort(num+1,num+n+1); tot=unique(num+1,num+tot+1)-num-1;
    	for(int i=tot;i>=1;i--) key[num[i]]=tot-i+1,_key[tot-i+1]=num[i];//reverse
    	for(int i=1;i<=n;i++) h[i]=key[h[i]],assert(h[i]!=0);
    	for(int i=1;i<=m;i++) KRU::e[i].in();
    	
    	all=rt=KRU::Kruskal(); TREE::Init(rt); SEG::Init();
    	int ans=0;
    	while(q--) {
    		int u,v,k; read(u); read(v); read(k);
    		u^=ans; v^=ans; k^=ans;
    		u=TREE::Find(u,v); 
    		// cerr<<'u'<<u<<"BD::"<<TREE::lim[u][0]<<" "<<v<<endl;
    		if(TREE::sz[u]<k) ans=0,puts("-1");
    		else {
    			ans=SEG::Query(SEG::rt[t_s[le[u]]-1],SEG::rt[t_s[le[u]]+TREE::sz[u]-1],1,n,k);
    			printf("%d
    ",ans=_key[ans]);
    		}
    	}
    	return 0;
    }
    /*
    10 11 4
    1 2 3 4 5 6 7 8 9 10
    1 4 4
    2 5 3
    9 8 2
    7 8 10
    7 1 4
    6 7 1
    6 4 8
    2 1 5
    10 8 10
    3 4 7
    3 4 6
    1 5 2
    1 5 6
    1 5 8
    8 9 2
    */
    

    用时:1.5h

  • 相关阅读:
    雷林鹏分享:XML to HTML
    雷林鹏分享:XML DOM
    雷林鹏分享:XML 编码
    雷林鹏分享: XML CDATA
    雷林鹏分享:服务器上的 XML
    雷林鹏分享:XML 注意事项
    雷林鹏分享:现实生活中的 XML
    雷林鹏分享:XML 相关技术
    雷林鹏分享:XML
    Android 系统架构图
  • 原文地址:https://www.cnblogs.com/functionendless/p/9498283.html
Copyright © 2011-2022 走看看