暑假集训CSP提高模拟9
又是挂分严重的一场
T1大众点评
T1交互题,注意边界处理,还有他的\(compare\)函数返回的是\(1,-1\),我以为是\(1,0\),爆零了
还有特判\(N=1\)的情况
点击查看代码
//#include "ramen.h"
//
//void Ramen(int N) {
// if(Compare(0, 1) == 1) {
// Answer(1, 0);
// } else {
// Answer(0, 1);
// }
//}
#include <bits/stdc++.h>
#include "ramen.h"
#define pb push_back
using namespace std;
void Ramen(int N) {
int n=N-1;
vector <int> los,win;
bool vis[N+100]={};
if(n==0)
{
Answer(0,0);
return;
}
for(int i=0;i<=n;i+=2)
{
if(i+1>n)break;
vis[i]=vis[i+1]=1;
if(Compare(i,i+1)==1)
{
win.pb(i);
los.pb(i+1);
}else
{
win.pb(i+1);
los.pb(i);
}
}
if(!vis[n])
{
if(Compare(win[0],n)==1)
{
los.pb(n);
}else
{
// auto it=lower_bound(win.begin(),win.end(),win[0]);
// win.erase(it,it+1);
win.pb(n);
}
}
int mx=win[0],mi=los[0];
for(int i=1;i<win.size();i++)
{
if(Compare(mx,win[i])==1)continue;
else mx=win[i];
}
for(int i=1;i<los.size();i++)
{
if(Compare(mi,los[i])==1)mi=los[i];
else continue;
}
Answer(mi,mx);
// if(Compare(0, 1) == 1) (x,y)=1 x>y
// {
// Answer(1, 0);
// } else
// {
// Answer(0, 1);
// }
}
//g++ -O2 -o grader grader.cpp ROM.cpp
//-std=c++14 -O2 -Wall
T2录取查询
线段树,很显然,说一下易错点
- 不能在\(pushup\)中判断\(cnt\)数组的合法性,因为左右还可以扩展,如果你当前让\(f\)变为\(0\),则之后都为\(0\),显然不是我们想要的,所以只需用\(f\)判断递增性即可
2.然后\(query\)函数返回结构体,再判断\(cnt\)数组的合法性
3.\(query\)传结构体时,注意赋值,如果当前未处理好,会影响到上一层回溯
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define ull unsigned long long
#define lid (rt<<1)
#define rid (rt<<1|1)
//#define endl '\n'
//#define int long long
#define pb push_back
using namespace std;
const int N = 1e5+5;const ull B=233;
int n,q,cnt[27];
string s,t;
struct Tree
{
int l,r;bool f;
char ls;char rs;
int cnt[28];
// void clear ()
// {
// l=-1;r=-1;f=0;
// ls=0;rs=0;
// memset(cnt,0,sizeof cnt);
// }
}st[N<<2];
inline void pushup(int rt)
{
int be=25,en=0;
st[rt].f=(st[lid].f&&st[rid].f&&st[lid].rs<=st[rid].ls);
for(int i=0;i<=25;i++)
{
st[rt].cnt[i]=st[lid].cnt[i]+st[rid].cnt[i];
}
st[rt].ls=st[lid].ls;st[rt].rs=st[rid].rs;
}
inline void bt(int rt,int l,int r)
{
// cout<<rt<<" "<<l<<" "<<r<<endl;
st[rt].l=l;st[rt].r=r;
if(l==r)
{
st[rt].cnt[s[l]-'a']++;
// st[rt].zt|=(1<<(s[l-1]-'a'));
st[rt].f=1;
st[rt].ls=st[rt].rs=s[l];
return;
}
int mid=(l+r)>>1;
bt(lid,l,mid);bt(rid,mid+1,r);
pushup(rt);
// cout<<l<<" "<<r<<" "<<st[rt].f<<endl;
}
void update(int rt,int l,int r,char v,char ls)
{
if(l<=st[rt].l&&st[rt].r<=r)
{
// cout<<l<<" "<<r<<endl;
st[rt].cnt[ls-'a']--;//!!!
st[rt].cnt[v-'a']++;
st[rt].ls=v;st[rt].rs=v;
st[rt].f=1;
return;
}
int mid=(st[rt].l+st[rt].r)>>1;
if(l<=mid)update(lid,l,r,v,ls);
else update(rid,l,r,v,ls);
pushup(rt);
}
Tree query(int rt,int l,int r)
{
if(l<=st[rt].l&&st[rt].r<=r)
{
// pushup(rt);
return st[rt];
}
int mid=(st[rt].l+st[rt].r)>>1;
Tree l1,r1,ans;
bool vl=0,vr=0;
if(l<=mid)vl=1,l1=query(lid,l,r);
if(r>mid)vr=1,r1=query(rid,l,r);
for(int i=0;i<=25;i++)ans.cnt[i]=l1.cnt[i]+r1.cnt[i];
if(vl&&vr)
{
ans.f=(l1.f&&r1.f&&(l1.rs<=r1.ls));
ans.ls=l1.ls;ans.rs=r1.rs;
}
else if(vl)ans=l1;
else if(vr)ans=r1;
return ans;
}
int main()
{
speed();
freopen("2.in","r",stdin);
freopen("B.out","w",stdout);
cin>>n>>s>>q;
// s.insert(0,'0');
s='*'+s;
for(int i=1;i<=n;i++)cnt[s[i]-'a']++;
int op,x,l,r;char c;
bt(1,1,n);
// cout<<"*****"<<endl;
while(q--)
{
cin>>op;
if(op==1)
{
cin>>x>>c;
char ls=s[x];
cnt[s[x]-'a']--;
s[x]=c;
cnt[s[x]-'a']++;
update(1,x,x,c,ls);
}else
{
cin>>l>>r;
Tree ans=query(1,l,r);
// cout<<ans.f<<endl;
// cout<<s.substr(l-1,r-l+1)<<endl;
if(ans.f)
{
bool f=1;
// cout<<ans.ls<<" "<<ans.rs<<endl;
for(int i=ans.ls+1;i<=ans.rs-1;i++)
{
if(cnt[i-'a']!=ans.cnt[i-'a'])
{
f=0;
break;
}
}
if(f)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
else cout<<"No"<<endl;
}
}
return 0;
}
T3精准打击
这道题,我考场上的思路是贪心的删最大的\(x\)子树,其实就是如此,一个大小为\(x\)的树,不一定是满\(K\)叉树,我们考虑先使一个大于等于\(x\)二二叉树分离,如果深度不为\(1\)则贡献为\(1\),然后再删他内部的部分子树,贪心的从大往小删,但是值得注意的是,第一次删的最大子树大小是不能确定的,所以我们要枚举,最后答案取\(min\)
点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define ull unsigned long long
#define lid (rt<<1)
#define rid (rt<<1|1)
//#define endl '\n'
//#define int long long
#define pb push_back
using namespace std;
const int N = 1e5+5;
ll d,x,k;__int128 p[N];
__int128 qpow(__int128 a,__int128 b)
{
__int128 ans=1;
while(b)
{
if(b&1)ans=a*ans;
b>>=1;a=a*a;
}
return ans;
}
__int128 fen(ll l,ll r,__int128 x)
{
ll ans=0;
while(l<=r)
{
ll mid=(l+r)>>1ll;
if(p[mid+1]-1==x)return mid;
if(p[mid+1]==x&&mid+1<=d)return mid;
if(p[mid+1]-1<x)
{
ans=mid;
r=mid-1;
}else l=mid+1;
}
return -ans;
}
void pt(__int128 x)
{
if(!x)return;
pt(x/10);
cout<<1ll*((ll)x%10);
}
int main()
{
speed();
// freopen("C.in","r",stdin);
// freopen("Cc.out","w",stdout);
int T;
cin>>T;
while(T--)
{
cin>>d>>k>>x;
bool ct=0;
p[0]=1;
for(ll i=1;i<=d;i++)
{
p[i]=p[i-1]*k+1;
}
ll cnt=0;ll ans=1e18;
for(int i=0;i<=d;i++)
{
cnt=0; ll tx=x;
if((p[i])>=x)
{
cnt= !(i==d);
ll tx=(p[i])-x;ll j=i-1;
while(tx&&~j)
{
cnt+=tx/(p[j]);
tx%=(p[j]);
j--;
}
ans=min(ans,cnt);
}
}
// ll ans=k-x+1;
cout<<ans<<endl;
}
return 0;
}