NOIP将近,由于我实力太菜,所以只能写写真题提升自己了。
P9868 [NOIP2023] 词典
简单字符串题,注意到可以换无限次,所以直接处理出每个字符串中最小的字符数和最大字符数就行了。
#include<bits/stdc++.h>
#define mxn 3010
using namespace std;
char s[mxn][mxn];
int n,m,cnt[mxn][27];
int minn[mxn],maxn[mxn],flg;
int main(){
//freopen("dict.in","r",stdin);
//freopen("a.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
memset(minn,0x3f,sizeof(minn));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>s[i][j];
cnt[i][s[i][j]-'a'+1]++;
minn[i]=min(minn[i],s[i][j]-'a'+1);
maxn[i]=max(maxn[i],s[i][j]-'a'+1);
}
for(int i=1;i<=n;i++){
flg=1;
for(int j=1;j<=n;j++){
if(i==j)continue;
if(minn[i]<maxn[j])continue;
flg=0;break;
}
if(flg)cout<<1;
else cout<<0;
}
return 0;
}
P9869 [NOIP2023] 三值逻辑
这题折腾了我一下午+三分之一个晚上,我真菜啊。
考虑用并查集将每个操作模拟。
每个值为 \(unknown\) 当且仅当出现两种情况:
\(1.\ x\) 的祖先是 \(-x\)。
\(2.\ x\) 的祖先为 \(unknwon\)。
这样判断就可以了。
同时,发现查询是会有负数,整体右移就行了。
对于死循环的情况,用 \(vis\) 数组判断就行了。
#include<bits/stdc++.h>
#define mxn 100010
#define U 0
#define T 100001
#define F -100001
using namespace std;
int n,m,_,type,ans;
int f[mxn],vis[mxn<<1];
int fnd(int u){
if(u==T||u==F||u==U)return u;
if(vis[-u+n])return U;
if(vis[u+n])return T;
if(u>0){
vis[u+n]=1;
int ret=fnd(f[u]);
f[u]=ret;
vis[u+n]=0;
return ret;
}
else{
vis[u+n]=1;
int ret=fnd(-f[-u]);
vis[u+n]=0;
return ret;
}
return 0;
}
void solve(){
ans=0;
cin>>n>>m;
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++){
char opt;cin>>opt;
if(opt=='T'){int x;cin>>x;f[x]=T;}
if(opt=='F'){int x;cin>>x;f[x]=F;}
if(opt=='U'){int x;cin>>x;f[x]=U;}
if(opt=='+'){int x,y;cin>>x>>y;f[x]=f[y];}
if(opt=='-'){int x,y;cin>>x>>y;f[x]=-f[y];}
}
for(int i=1;i<=n;i++)
if(fnd(i)==U)ans++;
cout<<ans<<'\n';
return;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>type>>_;
while(_--)solve();
return 0;
}
P9870 [NOIP2023] 双序列拓展
一开始很容易想到一个 \(35pts\) 的 \(O(qnm)\) 暴力。
根据特殊性质能发现,
我们找到 \(X\) 的最小值与 \(Y\) 的最大值的位置,把那一行和那一列标出来:
(偷题解的图)
发现如果能从左上角走到红线处,就可以从红线处走到右下角。
于是分治计算就行了。
#include<bits/stdc++.h>
#define ll long long
#define mxn 500010
using namespace std;
struct node{
int minn,maxn;
};
int c,q,a[mxn],b[mxn],xx[mxn],yy[mxn];
node prex[mxn],prey[mxn],sufx[mxn],sufy[mxn];
bool check1(int a,int b,int n,int m){
if(a==1||b==1)return 1;
if(xx[prex[a-1].minn]<yy[prey[b-1].minn])return check1(prex[a-1].minn,b,n,m);
if(xx[prex[a-1].maxn]<yy[prey[b-1].maxn])return check1(a,prey[b-1].maxn,n,m);
return 0;
}
bool check2(int a,int b,int n,int m){
if(a==n||b==m)return 1;
if(xx[sufx[a+1].minn]<yy[sufy[b+1].minn])return check2(sufx[a+1].minn,b,n,m);
if(xx[sufx[a+1].maxn]<yy[sufy[b+1].maxn])return check2(a,sufy[b+1].maxn,n,m);
return 0;
}
bool solve(int x[],int y[],int n,int m){
if(x[1]>=y[1])return 0;
for(int i=1;i<=n;i++)xx[i]=x[i];
for(int i=1;i<=m;i++)yy[i]=y[i];
prex[1]=node{1,1},prey[1]=node{1,1},sufx[n]=node{n,n},sufy[m]=node{m,m};
for(int i=2;i<=n;i++)
prex[i]=node{x[prex[i-1].minn]>x[i]?i:prex[i-1].minn,x[prex[i-1].maxn]<x[i]?i:prex[i-1].maxn};
for(int i=2;i<=m;i++)
prey[i]=node{y[prey[i-1].minn]>y[i]?i:prey[i-1].minn,y[prey[i-1].maxn]<y[i]?i:prey[i-1].maxn};
for(int i=n-1;i;i--)
sufx[i]=node{x[sufx[i+1].minn]>x[i]?i:sufx[i+1].minn,x[sufx[i+1].maxn]<x[i]?i:sufx[i+1].maxn};
for(int i=m-1;i;i--)
sufy[i]=node{y[sufy[i+1].minn]>y[i]?i:sufy[i+1].minn,y[sufy[i+1].maxn]<y[i]?i:sufy[i+1].maxn};
if(x[prex[n].maxn]>=y[prey[m].maxn])return 0;
if(x[prex[n].minn]>=y[prey[m].minn])return 0;
return check1(prex[n].minn,prey[m].maxn,n,m)&&check2(prex[n].minn,prey[m].maxn,n,m);
}
int x[mxn],y[mxn],n,m;
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>c>>n>>m>>q;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=m;i++)cin>>b[i];
if(solve(a,b,n,m)||solve(b,a,m,n))putchar('1');
else putchar('0');
while(q--){
for(int i=1;i<=n;i++)x[i]=a[i];
for(int i=1;i<=m;i++)y[i]=b[i];
int kx,ky;cin>>kx>>ky;
for(int i=1;i<=kx;i++){
int p,v;cin>>p>>v;x[p]=v;
}
for(int i=1;i<=ky;i++){
int p,v;cin>>p>>v;y[p]=v;
}
if(solve(x,y,n,m)||solve(y,x,m,n))putchar('1');
else putchar('0');
}
return 0;
}
P9871 [NOIP2023] 天天爱打卡
有点复杂的dp。
朴素的dp是从左到右遍历,枚举左端点。这样做 \(O(Tnmk)\),会炸飞。
然后我们考虑优化,能不能快速维护区间最大值和区间修改?可以用线段树解决。
#include<bits/stdc++.h>
#define ll long long
#define mxn 100010
#define pll pair<ll,ll>
#define pb push_back
#define mp make_pair
using namespace std;
ll n,m,k,d,c,t;
ll b[mxn<<1],len,cnt,dp[mxn<<1];
struct chlg{
ll x,y,v;
}a[mxn<<1];
vector<pll> p[mxn<<1];
namespace seg{
ll sum[mxn<<3],lazy[mxn<<3];
void push_down(ll rot){
sum[rot<<1]+=lazy[rot],sum[rot<<1|1]+=lazy[rot];
lazy[rot<<1]+=lazy[rot],lazy[rot<<1|1]+=lazy[rot];
lazy[rot]=0;
}
void push_up(ll rot){
sum[rot]=max(sum[rot<<1],sum[rot<<1|1]);
}
void build(ll rot,int l,int r){
sum[rot]=lazy[rot]=0;
if(l==r)return;
int mid=(l+r)>>1;
build(rot<<1,l,mid);
build(rot<<1|1,mid+1,r);
}
void add(ll rot,int l,int r,int x,int y,ll k){
if(l>=x&&r<=y){
sum[rot]+=k,lazy[rot]+=k;
return;
}
push_down(rot);
int mid=(l+r)>>1;
if(x<=mid)add(rot<<1,l,mid,x,y,k);
if(y>mid)add(rot<<1|1,mid+1,r,x,y,k);
push_up(rot);
}
ll query(ll rot,int l,int r,int x,int y){
if(l>=x&&r<=y)return sum[rot];
if(r<x||l>y)return 0;
push_down(rot);
int mid=(l+r)>>1;
return max(query(rot<<1,l,mid,x,y),query(rot<<1|1,mid+1,r,x,y));
}
}
void init(){
cnt=0;
cin>>n>>m>>k>>d;
for(int i=1;i<=m;i++){
cin>>a[i].y>>a[i].x>>a[i].v;
a[i].x=a[i].y-a[i].x+1;
b[++cnt]=a[i].x,b[++cnt]=a[i].y;
}
sort(b+1,b+cnt+1);
len=unique(b+1,b+cnt+1)-b-1;
for(int i=0;i<=len;i++)dp[i]=0;
seg::build(1,1,len);
return;
}
void solve(){
init();
for(int i=1;i<=m;i++){
a[i].x=lower_bound(b+1,b+len+1,a[i].x)-b;
a[i].y=lower_bound(b+1,b+len+1,a[i].y)-b;
p[a[i].y].pb(mp(a[i].x,a[i].v));
}
for(int i=1;i<=len;i++){
for(int j=0;j<p[i].size();j++){
pll pp=p[i][j];
seg::add(1,1,len,1,pp.first,pp.second);
}
dp[i]=max(dp[i],dp[i-1]);
int pos1=lower_bound(b+1,b+len+1,b[i]-k+1)-b;
int pos2=(b[i-1]==b[i]-1)?i-2:i-1;
ll dpi=dp[pos2>=0?pos2:0];
dp[i]=max(dp[i],seg::query(1,1,len,pos1,i-1)-b[i]*d-d);
dp[i]=max(dp[i],seg::query(1,1,len,i,i)+dpi-d);
seg::add(1,1,len,i,i,dpi+b[i]*d);
}
cout<<dp[len]<<'\n';
for(int i=1;i<=len;i++)p[i].clear();
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>c>>t;
while(t--)solve();
return 0;
}
标签:return,minn,int,笔记,mxn,maxn,NOIP2023,define
From: https://www.cnblogs.com/nagato--yuki/p/18515119