• 【LOJ #3161】「NOI2019」I 君的探险(随机化+整体二分)


    传送门

    首先是6868分对于树的做法(和正解没有关系)
    点编号为1n1-n
    考虑对于每一个二进制位dd
    把这编号位为1的点modifymodify
    然后对每个点queryquery
    如果颜色改变,那么sum+=1<<dsum+=1<<d
    然后可以发现这样求出来每一个点相连点的编号异或和

    然后考虑一个剥叶子的过程
    对于每一个点
    sum[u] modifysum[u] modify
    如果uu颜色改变
    那么uu之和sum[u]sum[u]相连
    于是就可以把这条边断开
    继续对sum[u]sum[u]操作

    可以发现对于树一定可以把所有边找出来
    复杂度O(nlogn)O(nlogn)
    不过有些特殊判断

    (namespace solve2)(代码namespace solve2)


    考虑对于一个点ii
    1,n1,n所有点除了iimodifymodify
    如果其颜色改变
    那么一定连了奇数条边出去
    然后对于1,mid1,mid进行modifymodify
    如果颜色也改变
    那么必定有奇数条边连向1,mid1,mid
    于是继续做

    对一个点是二分
    于是可以对所有点整体二分
    modify[l,mid],query(mid+1,r)modify[l,mid],query(mid+1,r)
    然后把询问挂到l,midl,mid
    题解说 可以证明随机情况下期望有n/3n/3的点像前连了奇数条边
    于是可以randrand一个排列这样做
    做完之后把所有孤立点checkcheck出除

    复杂度mlognmlogn

    #include "explore.h"
    #include<bits/stdc++.h>
    using namespace std;
    #define cs const
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define ll long long
    #define pb push_back
    cs int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?EOF:*ib++;
    }
    inline int read(){
    	char ch=gc();
    	int res=0;bool f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    inline int readstring(char *s){
    	int top=0;
    	char ch=gc();
    	while(isspace(ch))ch=gc();
    	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
    	return top;
    }
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int N=300005;
    int n,m;
    namespace solve1{
    	int sta[N];
    	inline void main(){
    		for(int i=0;i<n-1;i++){
    			modify(i);
    			for(int j=i+1;j<n;j++){
    				int now=query(j);
    				if(sta[j]!=now)report(i,j);
    				sta[j]=now;
    			}
    		}
    	}
    }
    namespace solve2{
    	int sta[N],sum[N];
    	queue<int> q;
    	map<pii,bool>vt;
    	inline void main(){
    		for(int i=0;(1<<i)<=n;i++){
    			for(int j=1;j<=n;j++)if(j&(1<<i)){
    				modify(j-1);
    			}
    			for(int j=1;j<=n;j++){
    				if(query(j-1)!=sta[j]){
    					sum[j]+=1<<i,sta[j]^=1;
    				}
    			}
    		}
    		for(int i=1;i<=n;i++)sum[i]^=i;
    		if(n%10>=7){
    			for(int i=n;i;i--)if(sum[i]){
    				report(i-1,sum[i]-1),sum[sum[i]]^=i;
    			}
    			return;
    		}
    		for(int i=1;i<=n;i++)q.push(i);
    		while(!q.empty()&&m){
    			int u=q.front();q.pop();
    			if(sum[u]>0&&sum[u]<=n&&sum[u]!=u&&vt.find(pii(min(sum[u],u),max(sum[u],u)))==vt.end()){
    				int pre=query(sum[u]-1);
    				modify(u-1);
    				if(query(sum[u]-1)!=pre){
    					report(sum[u]-1,u-1),m--;
    					q.push(sum[u]),vt[pii(min(sum[u],u),max(sum[u],u))]=1;
    					sum[sum[u]]^=u,sum[u]=0;
    				}
    			}
    		}
    	}
    }
    namespace solve3{
    	vector<int> q[N<<2];
    	vector<int> e[N];
    	int p[N],sta[N];
    	#define lc (u<<1)
    	#define rc ((u<<1)|1)
    	#define mid ((l+r)>>1)
    	void solve(int u,int l,int r){
    		if(l==r){
    			for(int &x:q[u]){
    				report(x,p[l]);
    				e[p[l]].pb(x),e[x].pb(p[l]);
    			}
    			return;
    		}
    		for(int i=l;i<=mid;i++){
    			modify(p[i]);
    			for(int &v:e[p[i]])sta[v]^=1;
    		}
    		for(int i=mid+1;i<=r;i++){
    			if(query(p[i])!=sta[p[i]])
    			q[lc].pb(p[i]);
    		}
    		for(int &x:q[u]){
    			if(query(x)!=sta[x])
    			q[lc].pb(x);
    			else q[rc].pb(x);
    		}
    		for(int i=l;i<=mid;i++){
    			modify(p[i]);
    			for(int &v:e[p[i]])sta[v]^=1;
    		}
    		solve(lc,l,mid),solve(rc,mid+1,r);
    	}
    	#undef lc
    	#undef rc
    	#undef mid
    	inline void main(){
    		srand(0721);
    		for(int i=0;i<n;i++)p[i+1]=i;
    		while(n){
    			random_shuffle(p+1,p+n+1);
    			for(int i=1;i<=n;i++)sta[p[i]]=query(p[i]);
    			solve(1,1,n);
    			for(int i=1;i<=n*4;i++)q[i].clear();
    			int nn=0;
    			for(int i=1;i<=n;i++)if(!check(p[i]))p[++nn]=p[i];
    			n=nn;
    		}
    	}
    }
    void explore(int _N, int _M) {
    	n=_N,m=_M;
    	if(n<=500)solve1::main();
    	else if(n>m)solve2::main();
    	else solve3::main();
    }
    
  • 相关阅读:
    oracle中的游标
    Oracle中的表空间
    Oracle中建表及表操作
    oracle中的权限管理
    oracle中的数据类型
    Oracle中常用的系统函数
    oracle中的dual表简介
    Oracle中常用的系统表
    Git常用命令总结
    Git配置文件与git config命令
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328348.html
Copyright © 2020-2023  润新知