• 8.10 NOI 模拟赛 whftll 分块 最短路 异或问题 结论


    LINK:whftll

    avatar
    avatar

    感觉这题很容易推出来 就差了临门一脚.

    失误的地方: 没有多画几种情况观察一下性质.

    固定一些变量 多画几种情况 有的时候就可以得到问题的性质 从而解题.

    35分做法:前20分

    考虑整个序列的异或和 要么为0 要么为给定数字.

    后者可以直接判断 而前者需要找到一个前缀异或和等于给定数字.

    带修改 查前缀异或和某个数字是否出现过 只能上分块.

    可以bitset 每次修改暴力重构某个块.

    subtask2 15分

    直接dp 复杂度(nQk)

    score 35
    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<ctime>
    #include<cctype>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000
    #define inf 100000000000ll
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define vep(p,n,i) for(RE int i=p;i<n;++i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007ll
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define ull unsigned long long
    #define ui unsigned
    #define EPS 1e-10
    #define sq sqrt
    #define S second
    #define F first
    #define id(i,j) ((i-1)*m+j)
    #define zz p<<1
    #define yy p<<1|1
    #define mod 1000000007
    #define min(x,y) ((x)>(y)?(y):(x))
    #define max(x,y) ((x)>(y)?(x):(y))
    using namespace std;
    char *fs,*ft,buf[1<<15];
    inline char gc()
    {
    	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
    	RE int x=0,f=1;RE char ch=gc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    	return x*f;
    }
    const int MAXN=100010,maxn=1100000,M=100003,N=352;
    int n,Q,B,ww,sj;
    int a[MAXN],pos[MAXN],b[MAXN],s[N],f[maxn],vis[maxn];
    int L[N],R[N],w[N];bitset<maxn>g[N];
    inline void modify(int x,int y)
    {
    	int p=pos[x];
    	rep(x,R[p],i)g[p][a[i]]=0;
    	ww^=b[x];b[x]=y;ww^=b[x];
    	if(x!=L[p])a[x]=a[x-1]^y;else a[x]=y;
    	rep(x+1,R[p],i)a[i]=a[i-1]^b[i];
    	rep(L[p],R[p],j)g[p][a[j]]=1;
    	w[p]=a[R[p]];
    }
    inline int ask(int x,int s)
    {
    	if(x>n)return n+1;
    	int p=pos[x],cc=0;
    	rep(1,p-1,i)cc=cc^w[i];
    	rep(x,R[p],i)if((a[i]^cc)==s)return i;
    	cc=cc^w[p];
    	rep(p+1,B,i)
    	{
    		if(g[i][cc^s])
    		{
    			rep(L[i],R[i],j)if((a[j]^cc)==s)return j;
    		}
    		cc=cc^w[i];
    	}
    	return n+1;
    }
    priority_queue<pii> q;
    inline bool solve(int m)
    {
    	while(q.size())q.pop();
    	++sj;q.push(mk(0,0));f[0]=0;
    	while(q.size())
    	{
    		pii x=q.top();q.pop();
    		int pos=-x.F;
    		if(pos!=f[x.S])continue;
    		rep(1,m,i)
    		{
    			int kk=s[i]^x.S;
    			int cc=ask(pos+1,kk);
    			if(cc==n+1)continue;
    			if(vis[kk]!=sj)
    			{
    				if(kk==ww)return 1;
    				vis[kk]=sj;
    				f[kk]=cc;
    				q.push(mk(-f[kk],kk));
    			}
    			else if(f[kk]>cc)f[kk]=cc,q.push(mk(-f[kk],kk));
    		}
    		
    	}
    	return 0;
    }
    int main()
    {
    	freopen("whftll.in","r",stdin);
    	freopen("whftll.out","w",stdout);
    	get(n);get(Q);
    	B=(int)sqrt(n*1.0);
    	int S=n/B;
    	rep(1,B,i)L[i]=S*(i-1)+1,R[i]=S*i;
    	R[B]=n;
    	rep(1,B,i)
    	{
    		rep(L[i],R[i],j)
    		{
    			b[j]=a[j]=read();
    			if(j!=L[i])a[j]^=a[j-1];
    			g[i][a[j]]=1;
    			pos[j]=i;
    		}
    		w[i]=a[R[i]];
    		ww=ww^w[i];
    	}
    	rep(1,Q,i)
    	{
    		int get(op);
    		if(op==1)
    		{
    			int get(x),get(y);
    			modify(x,y);
    		}
    		else
    		{
    			//rep(1,n,j)cout<<b[j]<<' ';
    			//cout<<ww<<endl;
    			int get(k);
    			rep(1,k,j)get(s[j]);
    			sort(s+1,s+1+k);
    			int num=0;
    			rep(1,k,j)if(j==1||s[j]!=s[j-1])s[++num]=s[j];
    			if(solve(num))puts("yes");
    			else puts("no");
    		}
    	}
    	return 0;
    }
    
    正解:

    多画几种情况 就可以发现 如果有解 那么一定有答案分的段数不超过(2^k)的解.

    原因是至多只有(2^k)种前缀和 如果存在两个前缀和一样 那么显然可以合并起来.

    而且考虑i处前缀和 如果和j处前缀和相同 那么如果(i<j) 那么j能转移的状态i也可以 所以j一定比i优.

    所以决策点最多只有(2^k)个.

    那么从0的位置开始每次暴力转移到下一个状态 且要保证某个状态的端点尽量靠前.

    这样可以利用dij来做 状态数为(2^kcdot k)

    然后 查以某个端点开始的前缀异或和 利用上述暴力的分块做法即可.

    sol
    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<ctime>
    #include<cctype>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000
    #define inf 100000000000ll
    #define ldb long double
    #define pb push_back
    #define put_(x) printf("%d ",x);
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define gi(x) scanf("%lf",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define vep(p,n,i) for(RE int i=p;i<n;++i)
    #define pii pair<int,int>
    #define mk make_pair
    #define RE register
    #define P 1000000007ll
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define ull unsigned long long
    #define ui unsigned
    #define EPS 1e-10
    #define sq sqrt
    #define S second
    #define F first
    #define id(i,j) ((i-1)*m+j)
    #define zz p<<1
    #define yy p<<1|1
    #define mod 1000000007
    #define min(x,y) ((x)>(y)?(y):(x))
    #define max(x,y) ((x)>(y)?(x):(y))
    using namespace std;
    char *fs,*ft,buf[1<<15];
    inline char gc()
    {
    	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
    	RE int x=0,f=1;RE char ch=gc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    	return x*f;
    }
    const int MAXN=100010,maxn=1100000,M=100003,N=352;
    int n,Q,B,ww,sj;
    int a[MAXN],pos[MAXN],b[MAXN],s[N],f[maxn],vis[maxn];
    int L[N],R[N],w[N];bitset<maxn>g[N];
    inline void modify(int x,int y)
    {
    	int p=pos[x];
    	rep(x,R[p],i)g[p][a[i]]=0;
    	ww^=b[x];b[x]=y;ww^=b[x];
    	if(x!=L[p])a[x]=a[x-1]^y;else a[x]=y;
    	rep(x+1,R[p],i)a[i]=a[i-1]^b[i];
    	rep(L[p],R[p],j)g[p][a[j]]=1;
    	w[p]=a[R[p]];
    }
    inline int ask(int x,int s)
    {
    	if(x>n)return n+1;
    	int p=pos[x],cc=0;
    	rep(1,p-1,i)cc=cc^w[i];
    	rep(x,R[p],i)if((a[i]^cc)==s)return i;
    	cc=cc^w[p];
    	rep(p+1,B,i)
    	{
    		if(g[i][cc^s])
    		{
    			rep(L[i],R[i],j)if((a[j]^cc)==s)return j;
    		}
    		cc=cc^w[i];
    	}
    	return n+1;
    }
    priority_queue<pii> q;
    inline bool solve(int m)
    {
    	while(q.size())q.pop();
    	++sj;q.push(mk(0,0));f[0]=0;
    	while(q.size())
    	{
    		pii x=q.top();q.pop();
    		int pos=-x.F;
    		if(pos!=f[x.S])continue;
    		rep(1,m,i)
    		{
    			int kk=s[i]^x.S;
    			int cc=ask(pos+1,kk);
    			if(cc==n+1)continue;
    			if(vis[kk]!=sj)
    			{
    				if(kk==ww)return 1;
    				vis[kk]=sj;
    				f[kk]=cc;
    				q.push(mk(-f[kk],kk));
    			}
    			else if(f[kk]>cc)f[kk]=cc,q.push(mk(-f[kk],kk));
    		}
    		
    	}
    	return 0;
    }
    int main()
    {
    	freopen("whftll.in","r",stdin);
    	freopen("whftll.out","w",stdout);
    	get(n);get(Q);
    	B=(int)sqrt(n*1.0);
    	int S=n/B;
    	rep(1,B,i)L[i]=S*(i-1)+1,R[i]=S*i;
    	R[B]=n;
    	rep(1,B,i)
    	{
    		rep(L[i],R[i],j)
    		{
    			b[j]=a[j]=read();
    			if(j!=L[i])a[j]^=a[j-1];
    			g[i][a[j]]=1;
    			pos[j]=i;
    		}
    		w[i]=a[R[i]];
    		ww=ww^w[i];
    	}
    	rep(1,Q,i)
    	{
    		int get(op);
    		if(op==1)
    		{
    			int get(x),get(y);
    			modify(x,y);
    		}
    		else
    		{
    			//rep(1,n,j)cout<<b[j]<<' ';
    			//cout<<ww<<endl;
    			int get(k);
    			rep(1,k,j)get(s[j]);
    			sort(s+1,s+1+k);
    			int num=0;
    			rep(1,k,j)if(j==1||s[j]!=s[j-1])s[++num]=s[j];
    			if(solve(num))puts("yes");
    			else puts("no");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    pip的认识
    java动态代理
    hadoop集群环境配置成功与否查看方法
    input输入框只能输入数字、字母相关组合
    ASP.NET Core MVC上传、导入、导出知多少
    MQTT
    高德地图
    油猴脚本
    excel中001如何输入
    WebPageBase.IsSectionDefined(String) 方法
  • 原文地址:https://www.cnblogs.com/chdy/p/13487970.html
Copyright © 2020-2023  润新知