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
咕咕咕
估计今年不会改了