zoukankan      html  css  js  c++  java
  • UOJ_407_【IOI2018】狼人

    http://uoj.ac/problem/407

    分析:

    • 分别建立最小/最大kruskal重构树。
    • 每次询问给出的两个点能走到的部分分别对应两棵树(dfs)序的一段区间。
    • 转化成判断矩形中是否有点。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    #include "werewolf.h"
    using namespace std;
    #define M 400050
    #define vi vector<int>
    int n,m,q_times,fa[M],ln;
    int dfn[2][M],enp[2][M],Ls[2][M],Rs[2][M],dfc,w[2][M];
    int f[2][20][M],idf[2][M],root[M],ls[M*22],rs[M*22],siz[M*22],cnt;
    char buf[100000],*p1,*p2;
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd() {
    	int x=0; char s=nc();
    	while(s<'0') s=nc();
    	while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    	return x;
    }
    struct A {
    	int a,b,c;
    	bool operator < (const A &u) const {
    		return c>u.c;
    	}
    }e[M];
    int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    void df1(int x,int o) {
    	dfn[o][x]=++dfc;
    	idf[o][dfc]=x;
    	if(Ls[o][x]) df1(Ls[o][x],o);
    	if(Rs[o][x]) df1(Rs[o][x],o);
    	enp[o][x]=dfc;
    }
    void update(int l,int r,int x,int &p,int q) {
    	p=++cnt; siz[p]=siz[q]+1; ls[p]=ls[q]; rs[p]=rs[q];
    	if(l==r) return ;
    	int mid=(l+r)>>1;
    	if(x<=mid) update(l,mid,x,ls[p],ls[q]);
    	else update(mid+1,r,x,rs[p],rs[q]);
    }
    int query(int l,int r,int x,int y,int p,int q) {
    	if(x<=l&&y>=r) return siz[p]-siz[q];
    	int mid=(l+r)>>1,re=0;
    	if(x<=mid) re+=query(l,mid,x,y,ls[p],ls[q]);
    	if(y>mid) re+=query(mid+1,r,x,y,rs[p],rs[q]);
    	return re;
    }
    vi check_validity(int n,vi EX,vi EY,vi QX,vi QY,vi QL,vi QR) {
    	ln=n*2-1;
    	m=EX.size();
    	int i,tot=n;
    	for(i=1;i<=m;i++) {
    		e[i].a=EX[i-1]; e[i].b=EY[i-1];
    		e[i].a++; e[i].b++;
    		e[i].c=min(e[i].a,e[i].b);
    	}
    	sort(e+1,e+m+1);
    	for(i=1;i<=ln;i++) fa[i]=i;
    	for(i=1;i<=m;i++) {
    		int dx=find(e[i].a),dy=find(e[i].b);
    		if(dx!=dy) {
    			fa[dx]=fa[dy]=++tot; Ls[0][tot]=dx; Rs[0][tot]=dy; w[0][tot]=e[i].c; f[0][0][dx]=f[0][0][dy]=tot;
    		}
    	}
    	df1(tot,0); dfc=0;
    	for(i=1;i<=ln;i++) fa[i]=i;
    	tot=n;
    	for(i=1;i<=m;i++) e[i].c=max(e[i].a,e[i].b);
    	sort(e+1,e+m+1);
    	for(i=m;i;i--) {
    		int dx=find(e[i].a),dy=find(e[i].b);
    		if(dx!=dy) {
    			fa[dx]=fa[dy]=++tot; Ls[1][tot]=dx; Rs[1][tot]=dy; w[1][tot]=e[i].c; f[1][0][dx]=f[1][0][dy]=tot;
    		}
    	}
    	df1(tot,1);
    	int j,k;
    	for(i=0;i<2;i++) {
    		for(j=1;(1<<j)<=ln;j++) {
    			for(k=1;k<=ln;k++) {
    				f[i][j][k]=f[i][j-1][f[i][j-1][k]];
    			}
    		}
    	}
    	for(i=1;i<=dfc;i++) {
    		root[i]=root[i-1];
    		int x=idf[1][i];
    		if(x<=n) {
    			update(1,dfc,dfn[0][x],root[i],root[i]);
    		}
    	}
    	vi ans;
    	int x,y,l,r;
    	q_times=QX.size();
    	for(j=0;j<q_times;j++) {
    		x=QX[j]; y=QY[j]; l=QL[j]; r=QR[j];
    		x++;y++;l++;r++;
    		for(i=19;i>=0;i--) {
    			if(f[0][i][x]&&w[0][f[0][i][x]]>=l) x=f[0][i][x];
    			if(f[1][i][y]&&w[1][f[1][i][y]]<=r) y=f[1][i][y];
    		}
    		int t=query(1,dfc,dfn[0][x],enp[0][x],root[enp[1][y]],root[dfn[1][y]-1]);
    		ans.push_back(t>0);
    	}
    	return ans;
    }
    
  • 相关阅读:
    百万英雄答题值不值得您继续参加
    一个程序员&自媒体人的2017年终总结
    送书福利又来了,总共10本程序员技术书
    CCF 201912-2 回收站选址(100分)Java
    CCF 201912-1 报数 (100分)Java
    CCF 201909-2 小明种苹果(续)(100分)Java
    CCF 201909-1 小明种苹果(100分)Java
    初识JWT
    Redis学习——事务、消息订阅和发布
    Redis学习——数据类型及操作
  • 原文地址:https://www.cnblogs.com/suika/p/10015472.html
Copyright © 2011-2022 走看看