NOIP2023 游记及反思
游记
进场前的同学们
柠檬熟了、Nitaycke、Prms_Prmt、b1t
zhicheng,meatherm
开题,很快啊,
第一题不就桶排,今年签到没有去年恶心啊(9:00)
第二题,观察到每个变量最后只有一个值的依靠(或者干脆定值),建图染色就好了啊,冲冲冲,9:30 就过完了样例
此时:优势在我!
第三题,发现就是区间匹配啊,转化为一个四联通的网格图走路,思考特殊性质,不会,思考 bitset 能不能艹 \(4\times 10^4\),没成功,35 pts 跑路。11:20 了,感觉比较寄
第四题,看起来我会 \(O(n^2)\) dp!我还会特殊性质 AB,那我是不是达到预期了啊,然后开始冲暴力。
写完数组,突然想到我的目的是完成挑战,开始结束一定在端点上,写个 dp 式子,发现和某个联考题很像,是可持久化李超?哦 \(ij\) 没有交错啊,那是不是单调队列啊。这个开始的价值动态更新,那扫描线掉区间右端点,加区间左端点,用线段树维护就完了。此时11:40,高兴麻了,那 300+ 是不是到 SC NOIP 队线了,开冲。
12:10 就写完了,怎么过不去样例啊?哦 \(xy\) 反了。测样例 \(2\),过不去,哦多测挂了。
然后还是过不去?为什么啊???
是不是结论假了啊?没道理啊。
…………
然后就没有然后了。
期望得分 \(100+100+35+0=235\),应该没挂分。
出考场不久就发现把相邻判成离散化后相邻了,艹艹艹!喜挂 \(100pts\) 😅!我草怎么考场上被机械降智了啊!原来的 \(335pts\) 至少也是遥遥领先我们机房的,现在寄了吧。
完蛋!我被降智包围了!♿♿♿。自闭。♿♿♿。暴力有 \(56\) 分,,,
出来发现 Meatherm 挂的更严重,第二题开始就心态炸完了。Hanghang 第一题看错了但是是对的(好像还挂了什么分),Nityacke 说他第一题 FailPreTest 了(是 \(10pts\) ),zhicheng 第三题写挂了,绷。
但是今年是 easy round 啊,是不是高二人均阿克了,高一希望比较渺茫啊。
补:高二机房没有 \(3\) 个会 T3 的,遥遥领先!优势在我啊!
反思:
前两道题倒是比较顺利。
第三题可能不在我目前的能力范围内,在时间充裕的时间内思考一个小时然后暴力是正确的。
最大的失误在第四题。第四题很快想出了正解,很快写完了,却没有考虑到这样的罕见的小细节;检查时,我使用了一般的检查方法,也重新思考了逻辑,感觉非常对,然后就没有发现错误。
事实上,如果我预先写好暴力,不仅至少我可以得到最低的暴力分,我应该也可以结合暴力和不算太大的样例 \(2\) 分析出错误。所以非签到题先打暴力显然是明智的选择。
赛后我发现,我犯错误的原因是这样:我在纸上写的 \(O(n^2)\) dp 方程是这样:
这里 \(c_j\) 是从 \(j\) 出发到 \(i\) 的贡献,使用扫描线,\(g\) 是这一个位置不跑步打卡的最大能量。
这是正确的。再结合“一定是从区间端点开始和结束”就可以获得离散化+线段树优化 dp 的正解。但是,这一把 \(O(n^2)\) dp 方程转化为 \(O(m^2)\)(未经线段树优化)的过程只在我脑中进行和代码用线段树实践了,未在纸上清晰地展示出来:这带来一些谬误,由离散化前后的值不同引起。
新的 dp 方程应该是这样:
\(rev\) 指离散化数组代指的原值。这对线段树优化的影响不大。
显然这是容易处理的,我却在脑袋里和代码里忽略了第一种情况,导致答案一直在某几个点偏小,最终也没有发现这个问题。所以,另一个教训是一定要把思路和可能想到的细节清晰地展现在纸上。
贴下代码吧
T1
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e3+5;
int n,m,cnt[maxn][27];
char s[maxn];
pair<int,int> p1[maxn][maxn],p2[maxn][maxn];
bool operator ==(pair<int,int> a,pair<int,int> b){
return a.first==b.first&&a.second==b.second;
}
signed main(){
// system("fc dict4.ans my.out");
freopen("dict.in","r",stdin);
freopen("dict.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>s+1;
for(int j=1;j<=m;j++)cnt[i][s[j]-'a'+1]++;
}
for(int i=1;i<=n;i++){
int c=0;
for(int k=1;k<=26;k++){
if(cnt[i][k])p1[i][++c]={k,cnt[i][k]};
}
for(int k=c+1;k<=26;k++)p1[i][k]={0,0};
c=0;
for(int k=26;k>=1;k--){
if(cnt[i][k])p2[i][++c]={k,cnt[i][k]};
}
for(int k=c+1;k<=26;k++)p2[i][k]={0,0};
}
for(int i=1;i<=n;i++){
bool ck=1;
for(int j=1;j<=n;j++){
if(i==j)continue;
bool can=0;
for(int k=1;k<=26;k++){
if(p1[i][k].second==0)break;
if(p1[i][k]!=p2[j][k]){
if(p1[i][k].first!=p2[j][k].first){
can=(p1[i][k].first<p2[j][k].first);
break;
}else{
can=0;
break;
}
}
}
if(!can){
// cout<<i<<" > "<<j<<endl;
ck=0;break;
}
}
cout<<ck;
}
return 0;
}
/*
4 7
abandon
bananaa
baannaa
notnotn
*/
T2
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
vector<pair<int,int> > e[maxn];
int val[maxn],C,Test,n,m,ans[maxn];
const int T=1e5+1,F=1e5+2,U=1e5+3;
int anti(int x){
if(x==T)return F;
if(x==F)return T;
if(x==U)return U;
return -x;
}
bool vis[maxn];
void add_edge(int u,int v,int w){
e[u].push_back({v,w});
e[v].push_back({u,w});
}
void dfs1(int u){
for(auto E:e[u]){
int v=E.first,w=E.second;
if(w)ans[v]=anti(ans[u]);
else ans[v]=ans[u];
if(!vis[v]){
vis[v]=1;
dfs1(v);
}
}
}
bool cur=1;
int cnt=0;
void dfs2(int u){
++cnt;
for(auto E:e[u]){
int v=E.first,w=E.second;
if(!vis[v]){
vis[v]=1;
if(w)ans[v]=anti(ans[u]);
else ans[v]=ans[u];
dfs2(v);
}else{
if(w){
if(ans[v]!=anti(ans[u]))cur=0;
}else{
if(ans[v]!=ans[u])cur=0;
}
}
}
}
signed main(){
freopen("tribool.in","r",stdin);
freopen("tribool.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>C>>Test;
while(Test--){
cin>>n>>m;
for(int i=1;i<=n;i++)val[i]=i;
for(int i=1;i<=m;i++){
char tp;int x,y;
cin>>tp;
if(tp=='T'){
cin>>x;
val[x]=T;
}else if(tp=='F'){
cin>>x;
val[x]=F;
}else if(tp=='U'){
cin>>x;
val[x]=U;
}else if(tp=='+'){
cin>>x>>y;
val[x]=val[y];
}else if(tp=='-'){
cin>>x>>y;
val[x]=anti(val[y]);
}
}
for(int i=1;i<=n;i++)e[i].clear();
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++){
if(val[i]<=(1e5)){
if(val[i]<0)add_edge(i,-val[i],1);
else add_edge(i,val[i],0);
}
}
for(int i=1;i<=n;i++){
if(val[i]>(1e5)){
ans[i]=val[i];
if(!vis[i])vis[i]=1,dfs1(i);
}
}
int Ans=0;
for(int i=1;i<=n;i++){
if(vis[i]==1&&ans[i]==U)++Ans;
}
for(int i=1;i<=n;i++){
if(!vis[i]){
cur=1;cnt=0;
vis[i]=1;ans[i]=T;
dfs2(i);
if(cur==0)Ans+=cnt;
}
}
cout<<Ans<<endl;
}
return 0;
}
/*
1 3
3 3
- 2 1
- 3 2
+ 1 3
3 3
- 2 1
- 3 2
- 1 3
2 2
T 2
U 2
*/
/*
Bless me
I wish that I can get more than 250 at NOIP
Then I may attend NOI2024 as NOID or even SC province team
rp++
British_union
*/
改过的 T4(就是那里错了/ll)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2e5+5;
int C,T,n,m,k,d;
int xds[maxn<<2],add[maxn<<2];
void ADD(int k,int v){
add[k]+=v,xds[k]+=v;
}
#define ls (k<<1)
#define rs (k<<1|1)
#define mid ((l+r)>>1)
void pushdown(int k){
ADD(ls,add[k]);
ADD(rs,add[k]);
add[k]=0;
}
void pushup(int k){
xds[k]=max(xds[ls],xds[rs]);
}
int query(int k,int l,int r,int x,int y){
// assert(xds[k]>=0);
if(x<=l&&r<=y)return xds[k];
pushdown(k);
int res=0;
if(x<=mid)res=max(res,query(ls,l,mid,x,y));
if(mid<y)res=max(res,query(rs,mid+1,r,x,y));
return res;
}
void modify(int k,int l,int r,int x,int y,int v){
// assert(v>=0);
if(x<=l&&r<=y)return ADD(k,v);
pushdown(k);
if(x<=mid)modify(ls,l,mid,x,y,v);
if(mid<y)modify(rs,mid+1,r,x,y,v);
pushup(k);
}
unordered_map<int,int> mp;
int l[maxn],r[maxn],v[maxn];
int qsy[maxn],rev[maxn],cnt=0,now=0;
vector<int> e[maxn];
int f[maxn],g[maxn];
signed main(){
// freopen("run.in","r",stdin);
// freopen("run.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>C>>T;
for(int zfy=1;zfy<=T;zfy++){
memset(xds,0,sizeof(xds));
memset(add,0,sizeof(add));
cin>>n>>m>>k>>d;
cnt=0;
for(int i=1;i<=m;i++){
int x,y;cin>>x>>y;
r[i]=x,l[i]=x-y+1;
cin>>v[i];
qsy[++cnt]=l[i],qsy[++cnt]=r[i];
}
sort(qsy+1,qsy+cnt+1);
mp.clear();
now=0;
for(int i=1;i<=cnt;i++){
if(!mp.count(qsy[i])){
mp[qsy[i]]=++now;
rev[now]=qsy[i];
}
}
// for(int i=1;i<=now;i++)cout<<i<<" "<<rev[i]<<endl;
for(int i=1;i<=m;i++)l[i]=mp[l[i]],r[i]=mp[r[i]];
for(int i=1;i<=now;i++)e[i].clear();
for(int i=1;i<=m;i++)e[r[i]].push_back(i);
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
int L=1,ans=0;
for(int i=1;i<=now;i++){
g[i]=max(g[i-1],f[i-1]);
modify(1,1,now,i,i,(rev[i]==rev[i-1]+1?g[i-1]:g[i])+rev[i]*d);
// modify(1,1,now,i,i,g[i-1]+rev[i]*d);
for(auto u:e[i]){
modify(1,1,now,1,l[u],v[u]);
}
while(L<i&&rev[i]-rev[L]+1>k)++L;
f[i]=-(rev[i]+1)*d+query(1,1,now,L,i);
}
cout<<max(g[now],f[now])<<endl;
}
return 0;
}
/*
1 1
3 2 2 1
2 2 4
3 2 3
*/
/*
I have nothing to say here.
*/
T3
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int x[maxn],y[maxn],xm[maxn],ym[maxn];
bool mp[2005][2005],vis[2005][2005];
bool solve(int a[],int b[],int n,int m){
if(a[1]>b[1])return solve(b,a,m,n);
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
mp[i][j]=(b[i]>a[j]);
}
}
if(!mp[1][1])return 0;
vis[1][1]=1;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(i==1&&j==1)continue;
vis[i][j]=(mp[i][j]&(vis[i-1][j]|vis[i][j-1]));
}
}
return vis[m][n];
}
bool solve2(int a[],int b[],int n,int m){
if(a[1]>b[1])return solve(b,a,m,n);
if(a[1]==b[1])return 0;
int r=1;
for(int i=1;i<=m;i++){
if(a[r]>=b[i])return 0;
while(r<=n&&a[r]<b[i])++r;
}
return 1;
}
int C,n,m,q;
signed main(){
freopen("expand.in","r",stdin);
freopen("expand.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>C>>n>>m>>q;
for(int i=1;i<=n;i++)cin>>x[i];
for(int i=1;i<=m;i++)cin>>y[i];
if(C<=7){
cout<<solve(x,y,n,m);
while(q--){
for(int i=1;i<=n;i++)xm[i]=x[i];
for(int i=1;i<=m;i++)ym[i]=y[i];
int kx,ky;cin>>kx>>ky;
while(kx--){
int p,v;cin>>p>>v;
xm[p]=v;
}
while(ky--){
int p,v;cin>>p>>v;
ym[p]=v;
}
cout<<solve(xm,ym,n,m);
}
}else{//Greedy
solve2(x,y,n,m);
while(q--){
for(int i=1;i<=n;i++)xm[i]=x[i];
for(int i=1;i<=m;i++)ym[i]=y[i];
int kx,ky;cin>>kx>>ky;
while(kx--){
int p,v;cin>>p>>v;
xm[p]=v;
}
while(ky--){
int p,v;cin>>p>>v;
ym[p]=v;
}
solve2(xm,ym,n,m);
}
}
return 0;
}
/*
3 3 3 3
8 6 9
1 7 4
1 0
3 0
0 2
1 8
3 5
1 1
2 8
1 7
*/
/*
I think this problem could be difiicult
But I can imagine that Meatherm,Nityacke(SC-114 henghengaa),Zhicheng and others can easily AC it
Such a pity that I have no ability to that :(
I love qsy
*/