[考试总结]noip模拟41

发现长时间鸽博客会导致 rp--,所以今天来补一补

这个题目其实不是很毒瘤,然而是非常毒瘤。。。

题目不说请就是非常非常的烦人

首先 \(T1\) 就整整有两个歧义的地方,也就是说我们一共有 \(4\) 种理解的方式。

非常恐怖

然后还有第四题,完全没看懂是个什么意思,然后 \(gg\) 了。

然后就是最让我伤心的 \(T2\) \(xin\)_\(team\) 打假。。。。。。。

非常伤心

你相信引力吗

我不相信题目

首先 任一 的意思不是任意一个,而是随意一个

nm

然后严格比 \(i\)\(j\) 高不是比其中一个高,而是比这两个都高

nm

之后这个题目就是很明白了。

我们其实可以使用单调栈来维护其左右端点。

还需要一个栈来维护其变化量。

这个变化量是相同元素的变化量。

就是:

\[\dbinom{n+1}{2}-\dbinom{n}{2}=n \]

之后就有了。。

#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#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++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
	{
		register bool f = 0;s = 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 = 1e7+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
	int st1[maxn],st2[maxn],top = 0,maxp = 0;
	int a[maxn],n;
	ll ans;
	inline short main()
	{
		io >> n;
		try(i,1,n)
		{
			io >> a[i]; a[n+i] = a[i];
			if(a[i] > a[maxp]) maxp = i;
		}
		try(i,maxp,maxp+n-1)
		{
			while(top and st1[top] < a[i]) ++ ans,top--;
			if(st1[top] > a[i]) ++ ans;
			else ans += st2[top] + (a[i] != a[maxp]);
			st1[++top] = a[i];
			st2[top] = (a[i] == st1[top-1]) ? st2[top-1] + 1 : 1;
		}
		while(top > 2) {if(st1[top] == st1[2]) break; ++ ans,top--;}
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

marshland

好吧,我现在还是垃圾 \(10\) 分。

正解应该是 \(nb\) 网络流。

毒瘤建图。。

party?

大佬们简单的想法应该是网络流。

但这个属实不是正解。

正解使用 \(bitset\) 进行模拟线段树。

之后还有一个什么霍尔定理关于二分图的完美匹配的东东。

#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#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++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7; const ll llinf = 1e18+7;
namespace xin
{
	#define bian(l,r) ((l + r) | ((l) != (r)))
	class xin_edge{public:int next,ver;}edge[maxn<<1];
	int head[maxn],zhi = 0;
	inline void add(int x,int y) {edge[++zhi].ver = y; edge[zhi].next = head[x]; head[x] = zhi;}
	int top[maxn],siz[maxn],d[maxn],hson[maxn],id[maxn],rk[maxn],tot = 0,fa[maxn];
	int n,m,a[maxn],qnum,q[maxn][11];
	void dfs1(int x,int f)
	{
		d[x] = d[f] + 1; siz[x] = 1;
		asm(i,x)
		{
			register int y = edge[i].ver;
			if(y == f) continue;
			dfs1(y,x);
			siz[x] += siz[y];
			if(siz[y] > siz[hson[x]]) hson[x] = y;
		}
	}
	void dfs2(int x,int t)
	{
		top[x] = t; id[x] = ++tot; rk[tot] = x;
		if(hson[x]) dfs2(hson[x],t);
		asm(i,x)
		{
			register int y = edge[i].ver;
			if(y == fa[x] or y == hson[x]) continue;
			dfs2(y,y);
		}
	}
	std::bitset<1024>bit1[maxn],bit2[maxn];
	void dfs3(int x)
	{
		if(x != top[x]) bit1[x] = bit1[fa[x]];
		bit1[x][a[x]] = 1; 
		asm(i,x) dfs3(edge[i].ver);
	}
	inline int lca(int x,int y)
	{
		while(top[x] xor top[y])
		{
			if(d[top[x]] < d[top[y]]) std::swap(x,y);
			x = fa[top[x]];
		}
		if(d[x] > d[y]) return y; return x;
	}
	void build(int l,int r)
	{
		if(l == r)
		{
			bit2[bian(l,r)][a[rk[l]]] = 1;
			return ;
		}
		register int mid = l + r >> 1;
		build(l,mid); build(mid+1,r);
		bit2[bian(l,r)] = bit2[bian(l,mid)] | bit2[bian(mid+1,r)];
	}
	std::bitset<1024> ask(int l,int r,int ql,int qr)
	{
		if(ql <= l and qr >= r) return bit2[bian(l,r)];
		register int mid = l + r >> 1;
		std::bitset<1024>ret;
		if(ql <= mid) ret |= ask(l,mid,ql,qr);
		if(qr >  mid) ret |= ask(mid+1,r,ql,qr);
		return ret;
	}
	inline std::bitset<1024> query(int x,int goal)
	{
		std::bitset<1024>ret;
		while(top[x] xor top[goal])
		{
			ret |= bit1[x];
			x = fa[top[x]];
		}
		ret |= ask(1,n,id[goal],id[x]);
		return ret;
	}
	inline short main()
	{
		io >> n >> m >> qnum;
		try(i,2,n)
		{
			io >> fa[i];
			add(fa[i],i);
		}
		try(i,1,n) io >> a[i];
		dfs1(1,0); dfs2(1,1);
		try(i,1,qnum)
		{
			io >> q[i][0];
			try(j,1,q[i][0]) io >> q[i][j];
		}
		dfs3(1); build(1,n);
		try(i,1,qnum)
		{
			int allca = lca(q[i][1],q[i][2]);
			try(j,3,q[i][0]) allca = lca(allca,q[i][j]);
			std::bitset<1024>temp[11];
			try(j,1,q[i][0]) temp[j] = query(q[i][j],allca);
//			try(j,1,q[i][0]) try(k,1,q[i][0]) cout<<temp[j][k];
//			cout<<endl;
			int ans = m,cnt = 0;
			for(int s=1;s<(1<<q[i][0]);s++)
			{
				int cnt=0;
				temp[0].reset();//jb(ans);
				for(int j=0;j<q[i][0];j++)
					if(s&(1<<j))
					{
						temp[0]|=temp[j+1];
						cnt++;
					}
				ans=std::min(ans,(int)temp[0].count()/cnt);
			}
			cout<<ans * q[i][0]<<endl;
		}
		return 0;
	}
}
signed main() {return xin::main();}

半夜

题目说明真的是垃圾。

这到题目实际上就是让我们求出一个最长循环上升子序列

然后这个玩意可以 \(\mathcal O(n^2)\) 求。

证明很毒瘤

放个码吧,细节很多。。

#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
	#define sb(x) cout<<#x" = "<<' '
	#define jb(x) cout<<#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++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
	#define scanf ak = scanf
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7; const ll llinf = 1e18+7;
namespace xin
{
	char s1[maxn],s2[maxn];
	int n;
	int f1[2010][4010],f2[2010][4010];
	inline short main()
	{
		scanf("%d",&n);
		scanf("%s%s",s1+1,s2+1);
		try(i,1,n) s2[i+n] = s2[i];
		try(i,1,(n << 1)) f1[0][i] = i;
		try(i,1,n)
			try(j,1,(n<<1))
			{
				register int x = f1[i-1][j],y = f2[i][j-1];
				if(s1[i] != s2[j] and x > y)
					f1[i][j] = x,f2[i][j] = y;
				else f1[i][j] = y,f2[i][j] = x;
			}
		int ans = 0;
//		try(i,1,n) {try(j,1,(n<<1)) cout<<f1[i][j]<<' '; cout<<endl;}
		try(i,1,n)
		{
			int temp = 0;
			try(j,i,n+i-1) if(i > f1[n][j]) temp ++;
			ans = std::max(ans,temp);
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}
posted @ 2021-08-22 11:15  NP2Z  阅读(38)  评论(0编辑  收藏  举报