CSP2021 游记

Day -29

初赛考得非常差,提高组只有可怜的 62.5pts。

还好北京线比较低,过了。

Day -28 ~ Day -2

zr 模拟赛,感受每场考试都被 czd 吊打的快乐

Day -1

被班主任请去喝茶(真正意义上的),喝完就饿了。。。感谢 wyl 的小饼干。

Day 0

在机房里快乐打板子,发现自己啥都不会,感觉要出事。。

Day 1

奶中了,寄了。还是稍微更一下吧。

普及组题很水吧,三个小时 AK 之后一直在五子棋,并被 Emacs 吊着打。被监考老师D了一顿之后就交卷跑路了。

中午睡了一觉,下午考提高组。

开 A 题,卧槽这什么玩意我咋不会,这玩意是不是单峰的啊,但我不会写整数三分啊。。。

去了趟厕所冷静一下,猜了个结论感觉挺对,开写!在大概一个小时的时候拍上了。

开 B 题,经过了漫长的阅读理解后终于读懂了题,并严重怀疑此题不可做。问候了出题人几十代祖宗之后终于冷静了下来,发现 dxy 暑假讲过类似的东西,好像思路直接搬过来就能做,于是手速拉满码了两个小时终于过了大样例。

还剩一个小时,开 C。没有读到每个数最多出现两次,于是乎自闭了十分钟,打了 28pts 的暴力跑路。开 D,没想到网络流一分不会,寻思着 test1 应该挺水,就写了个 \(\mathcal O(2^{nm}nm)\) 的玩意跑路(事实上 test1 很强)。

回来测冥间数据,自闭了。

A 题由于我在 set 里是这样 lower_bound 的:

auto it=lower_bound(s.begin(),s.end(),x) 

但 set 的 iterator 不是随机访问的,根据 C++ 标准这玩意是严格线性的,也就是说我考场上拿两个 \(\mathcal O(n^2)\) 的代码拍了一整场。。😅

改成 auto it=s.lower_bound(x) 就过了😅😅😅

40 + 100 + 28 + 0 = 168pts。

被吊打了,只希望能混个省一。

Day 8

出分了,45 + 100 + 28 + 0 = 173pts,北京 rk67。

还好没有挂更多的分。

自闭了,退役了。

Day ∞

为啥浙江分数线才 140


简要题解

普及组

candy

特判。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}

int main()
{
	//freopen("candy.in","r",stdin);
	//freopen("candy.out","w",stdout);
	int n=read(),L=read(),R=read();
	if(R-L+1>=n){printf("%d",n-1);return 0;}
	int now=R-(R%n-(n-1)+n)%n;
	if(now>=L){printf("%d",n-1);return 0;}
	printf("%d",R%n);
	return 0;
}

sort

记个 rank,然后每次操作线性修改。\(\mathcal O(Q+5000N)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
const int N=8010;
int a[N],pos[N];
struct node
{
	int val,pos;
}b[N];
bool cmp(node x,node y){return x.val==y.val?x.pos<y.pos:x.val<y.val;}
int main()
{
//	freopen("sort.in","r",stdin);
//	freopen("sort.out","w",stdout);
	int n=read(),q=read();
	for(int i=1;i<=n;i++)a[i]=read(),b[i].val=a[i],b[i].pos=i;
	sort(b+1,b+n+1,cmp);
	for(int i=1;i<=n;i++)pos[b[i].pos]=i;
	for(int i=1;i<=q;i++)
	{
		int p=read(),x=read();
		if(p==2)printf("%d\n",pos[x]);
		else
		{
			int v=read();
			for(int j=1;j<x;j++)if(a[j]>a[x])pos[j]--;
			for(int j=x+1;j<=n;j++)if(a[j]>=a[x])pos[j]--;
			a[x]=v;
			for(int j=1;j<x;j++)if(a[j]>a[x])pos[j]++;
			for(int j=x+1;j<=n;j++)if(a[j]>=a[x])pos[j]++;
			int cnt=1;
			for(int j=1;j<x;j++)if(a[j]<=a[x])cnt++;
			for(int j=x+1;j<=n;j++)if(a[j]<a[x])cnt++;
			pos[x]=cnt;
		}
//		for(int i=1;i<=n;i++)printf("%d ",a[i]);
//		puts("!!!");
//		for(int i=1;i<=n;i++)printf("%d ",pos[i]);
//		puts("!!!");
	}
	return 0;
}

network

模拟。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
const int N=1010;
bool check(string s)
{
	int cnt=0;//cnt of .
	int len=s.length(),num=0;
	bool f=0,mh=0;
	for(int i=0;i<len;i++)
	{
		if(s[i]>='0'&&s[i]<='9')
		{
			if(i+1<len&&!num&&s[i]=='0'&&(s[i+1]>='0'&&s[i+1]<='9'))return false;
			num=num*10+(s[i]-'0');
			if(num>1e6)return false;
			f=1;
		}
		if(s[i]=='.')
		{
			if(!f)return false;
			if(num<0||num>255)return false;
			cnt++;
			if(cnt>=4)return false;
			num=0;
			f=0;
		}
		if(s[i]==':')
		{
			if(!f)return false;
			if(num<0||num>255)return false;
			if(cnt!=3)return false;
			f=0,num=0;
			for(int j=i+1;j<len;j++)
			{
				if('0'<=s[j]&&s[j]<='9')
				{
					if(j+1<len&&!num&&s[j]=='0'&&(s[j+1]>='0'&&s[j+1]<='9'))return false;
					num=num*10+(s[j]-48);
					if(num>1e6)return false;
					f=1;
				}
				else return false;
			}
			if(!f)return false;
			if(num<0||num>65535)return false;
			mh=1;
			break;
		}
	}
	if(mh)return true;
	return false;
}
bool ff[N];//ff[i]:是否为服务机
bool ok[N];//ip是否合法
string s[N];
int main()
{
// 	freopen("network.in","r",stdin);
// 	freopen("network.out","w",stdout);
	ios::sync_with_stdio(false);
	int n;cin>>n;
//	cout<<check("1.1.1.1:1")<<"!!!"<<endl;
	for(int i=1;i<=n;i++)
	{
		string t;cin>>t;cin>>s[i];
		if(t[0]=='S')
		{
			ff[i]=1;
			ok[i]=check(s[i]);
			if(!ok[i])cout<<"ERR\n";
			else
			{
				bool f=1;
				for(int j=1;j<i;j++)if(ff[j]&&ok[j]&&s[j]==s[i]){f=0;break;}
				ok[i]=f;
				if(f)cout<<"OK\n";
				else cout<<"FAIL\n";
			}
		}
		else
		{
			ok[i]=check(s[i]);
			if(!ok[i])cout<<"ERR\n";
			else
			{
				int f=-1;
				for(int j=1;j<i;j++)if(ff[j]&&ok[j]&&s[j]==s[i]){f=j;break;}
				if(~f)cout<<f<<"\n";
				else cout<<"FAIL\n";
			}
		}
	}
}

fruit

每个块维护个 deque 或者 vector,然后启发式合并。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
const int N=2e5+10;
struct dsu{
	int f[N];
	void init(int n){for(int i=1;i<=n;i++)f[i]=i;}
	int getf(int x){return f[x]==x?x:f[x]=getf(f[x]);}
	void mg(int x,int y){f[getf(y)]=getf(x);}
}B;
int a[N];
deque<int> v[N];
set<int> s;
void merge(int x,int y)
{
//	printf("merge(%d, %d)!!\n",x,y);
	if(v[x].size()>v[y].size())swap(x,y);
	if(v[x][0]<v[y][0])for(int i=v[x].size()-1;i>=0;i--)v[y].push_front(v[x][i]);
	else for(int i=0;i<v[x].size();i++)v[y].push_back(v[x][i]);
	B.mg(y,x);
	s.erase(x);
}
vi Ans[N];
int cnt[N];
int main()
{
// 	freopen("fruit.in","r",stdin);
// 	freopen("fruit.out","w",stdout);
	int n=read();
	B.init(n);
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=2;i<=n;i++)if(a[i]==a[i-1])B.mg(i-1,i);
	for(int i=1;i<=n;i++)v[B.getf(i)].push_back(i),s.insert(B.getf(i));
	int c=0,now=0;
	while(1)
	{
		int prec=-1,pre=-1,Min=0x7fffffff;
		vector<int> tmp;
		for(set<int>::iterator it=s.begin();it!=s.end();it++)tmp.pb(*it),Min=min(Min,(int)v[*it].size());
		if(s.empty())break;
		for(int i=0;i<tmp.size();i++)
		{
			int cc=0;
			for(int j=0;j<Min;j++)
			{
				++cc,++c;
				Ans[now+cc].pb(v[tmp[i]][j]);
			}
			for(int j=0;j<Min;j++)v[tmp[i]].pop_front();
		}
		now+=Min;
		for(int i=0;i<tmp.size();i++)
		{
			int x=tmp[i];
			if(v[x].empty())s.erase(x);
			else{if(prec==a[x])merge(B.getf(pre),B.getf(x));prec=a[x],pre=x;}
		}
	}
	for(int i=1;i<=now;i++,puts(""))for(int j=0;j<Ans[i].size();j++)printf("%d ",Ans[i][j]);
	return 0;
}
//chenzida AK IOI!!!
//省队爷yyds!!!!!!!!!!!


/*
15
0 1 0 1 1 0 1 0 0 0 1 0 0 0 1 
*/

提高组

airport

考虑每新增一个廊桥,新加进来的一定是若干贪心选择的不相交的区间,set 维护即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
const int N=1e5+10;
int sum1[N],sum2[N];
struct node
{
	int l,r;
}a[N],b[N];
bool cmp(node x,node y){return x.l<y.l;}
int n,m1,m2;pii tmp[N];
bool vis1[N],vis2[N];
set<pii> s1,s2;
int main()
{
//	freopen("airport.in","r",stdin);
//	freopen("airport.out","w",stdout);
	n=read(),m1=read(),m2=read();
	for(int i=1;i<=m1;i++)a[i].l=read(),a[i].r=read();
	for(int i=1;i<=m2;i++)b[i].l=read(),b[i].r=read();
	sort(a+1,a+m1+1,cmp),sort(b+1,b+m2+1,cmp);
	for(int i=1;i<=m1;i++)s1.insert(mp(a[i].l,i));
	for(int i=1;i<=m2;i++)s2.insert(mp(b[i].l,i));
	int tot=0;
	for(int i=1;i<=m1;i++)
	{
		if(vis1[i])continue;
		int now=i,c=0;tot++;
		int cnt=0;
		while(1)
		{
			tmp[++cnt]=mp(a[now].l,now);
			vis1[now]=1;
			c++;
			set<pii>::iterator it=s1.lower_bound(mp(a[now].r,0));
			if(it==s1.end())break;
			now=it->se;
		}
		sum1[tot]=c;
		for(int j=1;j<=cnt;j++)s1.erase(tmp[j]);
	}
	tot=0;
	for(int i=1;i<=m2;i++)
	{
		if(vis2[i])continue;
		int now=i,c=0;tot++;
		int cnt=0;
		while(1)
		{
			tmp[++cnt]=mp(b[now].l,now);
			vis2[now]=1;
			c++;
			set<pii>::iterator it=s2.lower_bound(mp(b[now].r,0));
			if(it==s2.end())break;
			now=it->se;
		}
		sum2[tot]=c;
		for(int j=1;j<=cnt;j++)s2.erase(tmp[j]);
	}
	for(int i=1;i<=n;i++)sum1[i]+=sum1[i-1];
	for(int i=1;i<=n;i++)sum2[i]+=sum2[i-1];
	int ans=0;
	for(int i=0;i<=n;i++)ans=max(ans,sum1[i]+sum2[n-i]);
	printf("%d",ans);
	return 0;
}

bracket

区间 dp。\(f(l,r)\) 表示区间 \([l,r]\) 的方案数。转移考虑枚举 \(k\),钦定 \(s_l=\texttt{(},s_k=\texttt{)}\),再加上一些前缀和优化可以做到 \(\mathcal O(n^3)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
const int N=510,mod=1e9+7;
char s[N];int f[N][N],nxt[N],g[N][N],Sum[N][N];
int main()
{
//	freopen("bracket.in","r",stdin);
//	freopen("bracket.out","w",stdout);
	int n=read(),K=read();
	scanf("%s",s+1);
	for(int i=n,lst=n+1;i;i--)
	{
		if(s[i]=='('||s[i]==')')lst=i;
		nxt[i]=lst;
	}
	for(int i=1;i<n;i++)
	{
		if((s[i]=='('||s[i]=='?')&&(s[i+1]==')'||s[i+1]=='?'))
			f[i][i+1]=g[i][i+1]=1;
	}
	for(int len=3;len<=n;len++)
	{
		for(int r=1;r<=n;r++)
		{
			for(int l=1;l<=r;l++)
				Sum[l][r]=(Sum[l-1][r]+f[l][r])%mod;
		}
		for(int l=1;l+len-1<=n;l++)
		{
			int r=l+len-1;
			if(!((s[l]=='('||s[l]=='?')&&(s[r]==')'||s[r]=='?')))continue;
			bool ff=1;
			int cnt=0;	
			for(int j=l+1;j<r-1;j++)//[l+1,j]: ***
			{
				cnt++;
				if(cnt>K)break;
				if(s[j]!='?'&&s[j]!='*')break;
				g[l][r]+=f[j+1][r-1];
				g[l][r]%=mod;
			}
			cnt=0;
			for(int j=r-1;j>l+1;j--)//[j,r-1]: ***
			{
				cnt++;
				if(cnt>K)break;
				if(s[j]!='?'&&s[j]!='*')break;
				g[l][r]+=f[l+1][j-1];
				g[l][r]%=mod;
			}
			for(int j=l+1;j<r;j++)ff&=(s[j]=='?'||s[j]=='*');
			g[l][r]+=f[l+1][r-1],g[l][r]%=mod;
			if(ff&&r-l-1<=K)g[l][r]++,g[l][r]%=mod;
			f[l][r]+=g[l][r],f[l][r]%=mod;
			for(int k=l;k<r;k++)
			{
				int z=min(r,min(nxt[k+1],k+K+1));
				int sum=(Sum[z][r]-Sum[k][r]+mod)%mod;
				f[l][r]+=1ll*sum*g[l][k]%mod,f[l][r]%=mod;
			}
		}
	}
	printf("%d",f[1][n]);
}

palin

考虑第一个数在左边还是在右边取,然后维护两个队列贪心维护。

详见 https://www.luogu.com.cn/blog/ling-XAIqwq/solution-p7915

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return x*f;
}
void write(int n)
{
	if(n<0){putchar('-');n=-n;}
	if(n>9)write(n/10);
	putchar(n%10^48);
}
const int N=1e6+10;
int a[N];char ans[N];
void sol()
{
	int n=read();
	for(int i=1;i<=2*n;i++)a[i]=read();
	deque<int> A,B;
	A.push_back(a[1]);
	for(int i=2,zzt=0;i<=2*n;i++)
	{
		if(a[i]==a[1])
		{
			A.push_back(a[i]);
			zzt=1;
			continue;
		}
		if(!zzt)A.push_back(a[i]);
		else B.push_back(a[i]);
	}
	int pos=0;bool ff=1;
	while(pos<n)
	{
		++pos;bool f=1;
		if(A.size()>1ull&&A.front()==A.back())ans[pos]=ans[2*n-pos+1]='L',A.pop_front(),A.pop_back(),f=0;
		else if(!A.empty()&&!B.empty()&&A.front()==B.front())ans[pos]='L',ans[2*n-pos+1]='R',A.pop_front(),B.pop_front(),f=0;
		else if(!A.empty()&&!B.empty()&&B.back()==A.back())ans[pos]='R',ans[2*n-pos+1]='L',A.pop_back(),B.pop_back(),f=0;
		else if(B.size()>1ull&&B.back()==B.front())ans[pos]=ans[2*n-pos+1]='R',B.pop_front(),B.pop_back(),f=0;
		ff&=!f;if(!ff)break;
	}
	if(ff){for(int i=1;i<=2*n;i++)putchar(ans[i]);putchar('\n');return;}
	A.clear(),B.clear();
	B.push_back(a[2*n]);
	for(int i=2*n-1,zzt=0;i;i--)
	{
		if(a[i]==a[2*n])
		{
			A.push_front(a[i]);
			zzt=1;
			continue;
		}
		if(!zzt)B.push_front(a[i]);
		else A.push_front(a[i]);
	}
	pos=0,ff=1;
	while(pos<n)
	{
		++pos;bool f=1;
		if(A.size()>1ull&&A.front()==A.back())ans[pos]=ans[2*n-pos+1]='L',A.pop_front(),A.pop_back(),f=0;
		else if(!A.empty()&&!B.empty()&&A.front()==B.front())ans[pos]='L',ans[2*n-pos+1]='R',A.pop_front(),B.pop_front(),f=0;
		else if(!A.empty()&&!B.empty()&&B.back()==A.back())ans[pos]='R',ans[2*n-pos+1]='L',A.pop_back(),B.pop_back(),f=0;
		else if(B.size()>1ull&&B.back()==B.front())ans[pos]=ans[2*n-pos+1]='R',B.pop_front(),B.pop_back(),f=0;
		ff&=!f;if(!ff)break;
	}
	if(ff){for(int i=1;i<=2*n;i++)putchar(ans[i]);putchar('\n');return;}
	puts("-1");
}
int main()
{
	int T=read();
	while(T--)sol();
	return 0;
}

traffic

咕咕咕

估计今年不会改了

posted @ 2021-10-15 18:29  zzt1208  阅读(223)  评论(0编辑  收藏  举报