[考试总结]noip模拟78

F

开始没啥精神,感觉完全做不动。。。

然后发现这题目也没啥思路。。。

心态稍炸

然后发现答案一共只有 \(n^2\) 种取值,感觉看到曙光。

然后不会。。

然后又发现答案其实只有 \(n\) 种取值,感觉看到希望。

然后还是不会。。。

之后发现一个很妙的XIN队算法,然后对拍没错。

但是,复杂度。。。

\[\mathcal{O(2^n)}\\ n\leq 2000 \]

然后。。。

过了??!?!?!?!?

其实这个题目就是把式子移项,然后对于每一个可能的 \(x\) 进行check

考场代码



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
    #define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
    #define debug std::cerr<<"debug"<<endl
    #define sb(x) std::cerr<<#x" = "<<x<<' '
    #define jb(x) std::cerr<<#x" = "<<x<<endl
    #define scanf ak = scanf
    #define gec() getchar()
    #define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
    char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
    class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
    {
        s = 0; register bool f = 0; register char ch = gc();
        while(!isdigit(ch)) f |= ch == '-',ch = gc();
        while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
    }}io;
}
using namespace xin_io;static const int maxn = 1e6+10,inf = 1e9 + 10,two = 2e3+10;ll llinf = 1e18;
namespace xin
{
	int a[maxn],b[maxn];
	int temp[maxn<<2],zhi = 0;
	int n,m,pre;
	class xin_data
	{
		public:
			int pos,val;
			xin_data(){}
			xin_data(int pos,int val):pos(pos),val(val){}
	}d[two][two];
	bool vis[maxn];
	int l,r;
	bool dfs(int x,int val)
	{
		if(x == n + 1) return true;
		l = std::lower_bound(d[x]+1,d[x]+n+1,xin_data(0,val),[](xin_data x,xin_data y){return x.val < y.val;}) - d[x];
//		sb(x);jb(l);
		if(d[x][l].val != val) return false;
		r = std::upper_bound(d[x]+1,d[x]+n+1,xin_data(0,val),[](xin_data x,xin_data y){return x.val < y.val;}) - d[x] - 1;
//		sb(x); jb(r);
		try(i,l,r) if(!vis[d[x][i].pos])
		{
			vis[d[x][i].pos] = 1;
			if(dfs(x+1,val)) return true;
			vis[d[x][i].pos] = 0;
		}
		return false;
	}
	int out[maxn],ans;
	inline short main()
	{
		freopen("f.in","r",stdin);
		freopen("f.out","w",stdout);
		io >> n;
		try(i,1,n) io >> a[i]; try(i,1,n) io >> b[i];
		try(i,1,n)
		{
			try(j,1,n)
			{
				d[i][j].pos = j;
				d[i][j].val = a[i] xor b[j];
				temp[++zhi] = a[i] xor b[j];
			}
			std::sort(d[i]+1,d[i]+n+1,[](xin_data x,xin_data y)->bool{return (x.val == y.val) ? x.pos < y.pos:x.val < y.val;});
		}
		try(i,1,n)
		{
			if(i - 1 and d[1][i].val == d[1][i-1].val) continue;
//			jb(d[1][i].val);
			memset(vis,0,sizeof(bool) * (n + 1));
			if(dfs(1,d[1][i].val)) out[++ans] = d[1][i].val;
		}
		cout<<ans<<endl;
		try(i,1,ans) printf("%d\n",out[i]);
/*		try(i,1,n)
		{
			jb(i);
			try(j,1,n) 
				sb(d[i][j].val),jb(d[i][j].pos);
			cout<<endl;
		}*/
//		dfs(1,9);
		return 0;
	}
}
signed main() {return xin::main();}

正解:



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
	#define sb(x) std::cerr<<#x" = "<<x<<' '
	#define jb(x) std::cerr<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	#define gec() getchar()
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
	class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
	{
		s = 0; register bool f = 0; register char ch= gc();
		while(!isdigit(ch)) f |= ch == '-',ch = gc();
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,two = 2e2+10,inf = 1e9+10;
//#define int long long
namespace xin
{
	std::unordered_map<int,int>ton;
	int a[maxn],b[maxn];
	int ans[maxn],zhi = 0;
	int out[maxn],cnt = 0;
	int n;
	auto check = [](int x) -> bool
	{
		try(i,1,n)
		{
			ton[x xor b[i]] --;
			if(ton[x xor b[i]] < 0) return false;
		}
		try(i,1,n) if(ton[a[i]]) return false;
		return true;
	};
	inline short main()
	{
	#ifdef ONLINE_JUDGE
		file(f);
	#endif
		io >> n;
		try(i,1,n) io >> a[i]; try(j,1,n) io >> b[j];
		try(j,1,n)
		{
			try(i,1,n) ton[a[i]] = 0;
			try(i,1,n) ton[a[i]] ++;
			if(check(a[1] xor b[j])) out[++zhi] = a[1] xor b[j];
		}
		std::sort(out+1,out+zhi+1);
		printf("%d\n",zhi);
		try(i,1,zhi) printf("%d\n",out[i]);
		return 0;
	}
}
signed main() {return xin::main();}

s

考场上为了骗分,写了一个假的贪心。

然后骗了 \(40\) 之多。

其实就是让我求一个最小逆序对。

设 \(f_{i,j,k,0/1/2}\) 为选了 \(i\) 个 \(R\),\(j\) 个 \(G\),\(K\) 个 \(B\),然后结尾是什么的答案之后愉快转移。



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
	#define sb(x) std::cerr<<#x" = "<<x<<' '
	#define jb(x) std::cerr<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	#define gec() getchar()
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
	class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
	{
		s = 0; register bool f = 0; register char ch= gc();
		while(!isdigit(ch)) f |= ch == '-',ch = gc();
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,two = 2e2+10,inf = 1e9+10;
//#define int long long
namespace xin
{
	int f[two][two][two][3];
	int n,cnt[maxn];
	int st[two][two];
	char s[maxn];
	auto get = [](char ch) 
	{
		if(ch == 'R') return 0;
		if(ch == 'G') return 1;
		return 2;
	};
	inline short main()
	{
	#ifdef ONLINE_JUDGE
		file(s);
	#endif
		scanf("%lld%s",&n,s+1);
		try(i,1,n) 
		{
			register int bian = get(s[i]);
			st[bian][++cnt[bian]] = i;
		}
		memset(f,0x3f,sizeof(f));
		f[1][0][0][0] = f[0][1][0][1] = f[0][0][1][2] = 0;
		try(i,0,cnt[0]) try(j,0,cnt[1]) try(k,0,cnt[2])
		{
			if(i > 0)
			{
				int ret = 0;
				if(j > 0) ret += j - (std::lower_bound(st[1]+1,st[1]+j+1,st[0][i]) - st[1] - 1);
				if(k > 0) ret += k - (std::lower_bound(st[2]+1,st[2]+k+1,st[0][i]) - st[2] - 1);
				if(j > 0) f[i][j][k][0] = std::min(f[i][j][k][0],f[i-1][j][k][1] + ret);
				if(k > 0) f[i][j][k][0] = std::min(f[i][j][k][0],f[i-1][j][k][2] + ret);
			}
			if(j > 0)
			{
				int ret = 0;
				if(i > 0) ret += i - (std::lower_bound(st[0]+1,st[0]+i+1,st[1][j]) - st[0] - 1);
				if(k > 0) ret += k - (std::lower_bound(st[2]+1,st[2]+k+1,st[1][j]) - st[2] - 1);
				if(i > 0) f[i][j][k][1] = std::min(f[i][j][k][1],f[i][j-1][k][0] + ret);
				if(k > 0) f[i][j][k][1] = std::min(f[i][j][k][1],f[i][j-1][k][2] + ret);
			}
			if(k > 0)
			{
				int ret = 0;
				if(i > 0) ret += i - (std::lower_bound(st[0]+1,st[0]+i+1,st[2][k]) - st[0] - 1);
				if(j > 0) ret += j - (std::lower_bound(st[1]+1,st[1]+j+1,st[2][k]) - st[1] - 1);
				if(i > 0) f[i][j][k][2] = std::min(f[i][j][k][2],f[i][j][k-1][0] + ret);
				if(j > 0) f[i][j][k][2] = std::min(f[i][j][k][2],f[i][j][k-1][1] + ret);
			}
		}
		int ans = inf;
		try(i,0,2) ans = std::min(f[cnt[0]][cnt[1]][cnt[2]][i],ans);
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

y

不会

o

垃圾数据,暴力水过。。



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
	#define sb(x) std::cerr<<#x" = "<<x<<' '
	#define jb(x) std::cerr<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	#define gec() getchar()
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
	class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
	{
		s = 0; register bool f = 0; register char ch= gc();
		while(!isdigit(ch)) f |= ch == '-',ch = gc();
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,two = 1e2+10;
#define int long long
namespace xin
{
	int a[maxn],n;
	class xin_seg
	{
		private:
			#define ls(fa) (fa << 1)
			#define rs(fa) (fa << 1 | 1)
			#define up(fa) (t[fa].s = t[ls(fa)].s + t[rs(fa)].s)
		public:
			class xin_tree{public:int s;}t[maxn];
			void build(int fa,int l,int r)
			{
				if(l == r) return t[fa].s = a[l],void();
				register int mid = l + r >> 1;
				build(ls(fa),l,mid); build(rs(fa),mid+1,r);
				up(fa);
			}
			void modify(int fa,int l,int r,int pos,int val)
			{
				if(l == r) return t[fa].s = val,void();
				register int mid = l +  r >> 1;
				if(pos <= mid) modify(ls(fa),l,mid,pos,val);
				else modify(rs(fa),mid+1,r,pos,val);
				up(fa);
			}
			int query(int fa,int l,int r,int ql,int qr)
			{
				if(ql <= l and qr >= r) return t[fa].s;
				register int mid = l + r >> 1,ret = 0;
				if(ql <= mid) ret += query(ls(fa),l,mid,ql,qr);
				if(qr >  mid) ret += query(rs(fa),mid+1,r,ql,qr);
				return ret;
			}
	}t;
	class xin_query
	{
		private:
			friend bool operator < (const xin_query &x,const xin_query &y){return x.t < y.t;}
		public:
			int t,l,r,id;
	}q[maxn];
	int st[maxn],zhi = 0;
	class xin_data
	{
		public:
			int id,w;
			xin_data(){}
			xin_data(int id,int w):id(id),w(w){}
	}d[maxn];
	std::vector<xin_data> vec[maxn];
	int ans[maxn],qnum;
	inline short main()
	{
	#ifdef ONLINE_JUDGE
		file(o);
	#endif
		io >> n >> qnum;
		try(i,1,n) io >> a[i]; try(i,1,qnum) io >> q[i].t >> q[i].l >> q[i].r,q[i].id = i;
		try(i,1,n)
		{
			while(zhi and a[i] >= a[st[zhi]]) zhi --;
			try(j,1,zhi) vec[i-st[j]].push_back(xin_data(i,a[st[j]]));
			st[++zhi] = i;
		}
		t.build(1,1,n);
		std::sort(q+1,q+qnum+1);
		try(i,1,qnum)
		{
			if(q[i].t != q[i-1].t)
			{
				try(j,q[i-1].t+1,q[i].t)
				{
					if(j > n) break;
					for(auto x : vec[j]) t.modify(1,1,n,x.id,x.w);
				}
			}
			ans[q[i].id] = t.query(1,1,n,q[i].l,q[i].r);
		}
		try(i,1,qnum) printf("%lld\n",ans[i]);
		return 0;
	}
}
signed main() {return xin::main();}
上一篇:NOIP模拟82


下一篇:NOIP 模拟 七十四