省选模拟39
然后我又垫底了......
不想写题解ing
T1 逃离藏宝洞
发现可以每次跳个40步,然后因为一定是先上升再下降的,所以我们可以跳到路径最高点!!
期望步数是一半!!
AC_code
#include<bits/stdc++.h>
#include"escape.h"
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
int now,las;
void spj1(){
bool fl=false;
move(0);fl=true;las=0;
if(query()<now)move(0),fl=false;
if(!fl){
move(1);fl=true;las=1;
if(query()<now)move(1),fl=false;
}
if(!fl){move(2);las=2;}
now++;
while(now){
if(las==0){
move(1);fl=true;las=1;
if(query()<now)move(1),fl=false;
if(!fl)move(2),las=2;
now++;
}
else if(las==1){
move(0);fl=true;las=0;
if(query()<now)move(0),fl=false;
if(!fl)move(2),las=2;
now++;
}
else if(las==2){
move(1);fl=true;las=1;
if(query()<now)move(1),fl=false;
if(!fl)move(0),las=0;
now++;
}
}
}
random_device you;
mt19937 pyt(you());
int rd(int l,int r){
uniform_int_distribution<> ee(l,r);
return ee(pyt);
}
int ji[100],cj,lim;
int ano(int x){
return x==0?1:(x==1?2:0);
}
void jump(){
cj=0;ji[0]=las;
// cerr<<now<<" "<<query()<<endl;
fo(i,1,lim){
int tmp=ji[cj];
ji[++cj]=pyt()%2?ano(tmp):ano(ano(tmp));
// cerr<<ji[cj]<<endl;
if(ji[cj]==ji[cj-1])ji[cj]=0;
assert(ji[cj]>=0&&ji[cj]<=2);
move(ji[cj]);
// cerr<<ji[cj]<<" "<<ji[cj-1]<<" "<<query()<<endl;
}
// cerr<<endl;
int res=query(),tmp=res;
// cerr<<res<<endl;
// cerr<<now<<" "<<lim<<" "<<res<<endl;
// cerr<<"SB"<<" "<<(now+lim-tmp>>1)<<endl;
fo(i,1,(now+lim-tmp)>>1){
// cerr<<cj<<endl;
assert(ji[cj]>=0&&ji[cj]<=2);
move(ji[cj--]),res++;
}
now=res;
// cerr<<now<<" "<<query()<<" ";
// cerr<<cj<<endl;
if(cj!=lim){
if(ji[cj]!=0&&ji[cj+1]!=0)move(0),las=0;
if(ji[cj]!=1&&ji[cj+1]!=1)move(1),las=1;
if(ji[cj]!=2&&ji[cj+1]!=2)move(2),las=2;
now++;
}
else las=ji[cj];
// cerr<<query()<<" "<<now<<endl;
// exit(0);
}
void escape(int lm, int lq){
now=query();
if(lq>=-now){spj1();return ;}
bool fl;lim=lm/(-now)/2;
move(0);fl=true;las=0;
if(query()<now)move(0),fl=false;
if(!fl){
move(1);fl=true;las=1;
if(query()<now)move(1),fl=false;
}
if(!fl){move(2);las=2;}
now++;
// cerr<<now<<" "<<query()<<" "<<las<<endl;
while(now<0)jump();
}
T2 序列划分
线段树模板题
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1e6+5;
const int mod=998244353;
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
int n,a[N],mex[N],nxt[N],vis[N];
struct XDS{
#define ls x<<1
#define rs x<<1|1
int mn[N*4],tg[N*4],sn[N*4];
int sm[N*4],ts[N*4],tj[N*4];
void pushup(int x){
mn[x]=min(mn[ls],mn[rs]);
sn[x]=(sn[ls]+sn[rs])%mod;
// sm[x]=(sm[ls]+sm[rs])%mod;
return ;
}
void pushdown(int x,int l,int r){
int mid=l+r>>1;
if(tj[x]){
tj[ls]=(tj[ls]+tj[x])%mod;
if(mid==l)sm[ls]=(sm[ls]+tj[x]*(mid-l+1))%mod;
tj[rs]=(tj[rs]+tj[x])%mod;
if(r==mid+1)sm[rs]=(sm[rs]+tj[x]*(r-mid))%mod;
tj[x]=0;
}
if(ts[x]){
if(~tg[ls])tj[ls]=(tj[ls]+ts[x]*mn[ls])%mod;
else ts[ls]=(ts[ls]+ts[x])%mod;
if(mid==l)sm[ls]=(sm[ls]+sn[ls]*ts[x])%mod;
if(~tg[rs])tj[rs]=(tj[rs]+ts[x]*mn[rs])%mod;
else ts[rs]=(ts[rs]+ts[x])%mod;
if(r==mid+1)sm[rs]=(sm[rs]+sn[rs]*ts[x])%mod;
ts[x]=0;
}
if(~tg[x]){
tg[ls]=mn[ls]=tg[x];
if(l==mid)sn[ls]=tg[x]*(mid-l+1)%mod;
tg[rs]=mn[rs]=tg[x];
if(r==mid+1)sn[rs]=tg[x]*(r-mid)%mod;
tg[x]=-1;
}
tg[x]=-1;return ;
}
void build(int x,int l,int r){
tg[x]=-1;ts[x]=tj[x]=0;
if(l==r){
sm[x]=mn[x]=sn[x]=mex[l];
return ;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(x);return ;
}
int query(int x,int l,int r,int qr,int v){
if(r<=qr){
if(mn[x]>=v){
tg[x]=v;mn[x]=v;
sn[x]=v*(r-l+1)%mod;
return l;
}
if(l==r)return r+1;
int mid=l+r>>1,ret=0;
if(~tg[x]||tj[x]||ts[x])pushdown(x,l,r);
ret=query(rs,mid+1,r,qr,v);
if(ret==mid+1)ret=query(ls,l,mid,qr,v);
pushup(x);return ret;
}
int mid=l+r>>1,ret=0;
if(~tg[x]||tj[x]||ts[x])pushdown(x,l,r);
if(qr>mid)ret=query(rs,mid+1,r,qr,v);
if(!ret||ret==mid+1)ret=query(ls,l,mid,qr,v);
pushup(x);return ret;
}
void ins_sm(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){
if(~tg[x])tj[x]=(tj[x]+v*mn[x])%mod;
else ts[x]=(ts[x]+v)%mod;
sm[x]=(sm[x]+v*sn[x])%mod;
return ;
}
int mid=l+r>>1;
if(~tg[x]||tj[x]||ts[x])pushdown(x,l,r);
if(ql<=mid)ins_sm(ls,l,mid,ql,qr,v);
if(qr>mid)ins_sm(rs,mid+1,r,ql,qr,v);
pushup(x);return ;
}
int qry(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return sm[x];
int mid=l+r>>1,ret=0;
if(~tg[x]||tj[x]||ts[x])pushdown(x,l,r);
if(ql<=mid)ret=(ret+qry(ls,l,mid,ql,qr))%mod;
if(qr>mid)ret=(ret+qry(rs,mid+1,r,ql,qr))%mod;
pushup(x);return ret;
}
#undef ls
#undef rs
}xds;
signed main(){
freopen("divide.in","r",stdin);
freopen("divide.out","w",stdout);
// cerr<<(sizeof(xds)+sizeof(a)*5>>20)<<endl;
n=read();
fo(i,1,n)a[i]=read();
fo(i,1,n){
if(a[i]<=n){
nxt[vis[a[i]]]=i;
vis[a[i]]=i;
}
mex[i]=mex[i-1];
while(vis[mex[i]])mex[i]++;
}
xds.build(1,1,n);
fo(i,1,n-1){
if(!nxt[i])nxt[i]=n+1;
if(a[i]<=n)xds.query(1,1,n,nxt[i]-1,a[i]);
int now=xds.qry(1,1,n,i,i);
xds.ins_sm(1,1,n,i+1,n,now);
}
printf("%lld",xds.qry(1,1,n,n,n));
return 0;
}
T3 重排列
考场上一直在想如何贪心,但是还是没有找到一个符合两个人策略的最优解
发现B是不能改变两个不互质的数的相对顺序的
所以我们先给不互质的数连边,我们会形成许多个联通块,这些联通块之间是互相独立的
如果求出来每个联通块的顺序,用优先队列合并就好了
那么在一个联通块中我们肯定选最小的那个,于是删掉他,递归解决!!
不要看码,我是智障写了120
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=2005;
int n,a[N],ans[N*2][N],cas;
struct node{
int v,bl,tp;
}nd[N*20];
int cnd;
struct E{int to,nxt;}e[N*20];
int head[N*20],rp;
void add_edg(int x,int y){e[++rp].to=y;e[rp].nxt=head[x];head[x]=rp;}
map<int,int> mp;
bool ban[N*20],ok[N*20];
struct nod{
int v,id;
bool operator < (nod a)const{
return ans[id][v]<ans[a.id][a.v];
}
};
void dfs(int x,int v,int las,int mn,int d){
// cerr<<x<<" "<<d<<" "<<v<<" "<<nd[x].v<<" "<<las<<endl;
if(nd[x].bl!=las||ban[x])return ;
nd[x].bl=v;
if(d)ok[x]=true;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==mn)ok[x]=true;
if(nd[y].bl!=las||ban[y])continue;
dfs(y,v,las,mn,(d&&x>n));
}
}
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
void sol(int x,int f,int las){
// cerr<<"sol"<<" "<<x<<" "<<f<<endl;
int mn=-1;
fo(i,1,n){
if(x==0){mn=0;break;}
// cerr<<i<<" "<<nd[i].bl<<endl;
if(ban[i]||(gcd(nd[i].v,nd[las].v)==1&&nd[i].v!=1&&nd[las].v!=1)||nd[i].bl!=x)continue;
// cerr<<nd[i].v<<endl;
if(mn==-1||nd[i].v<nd[mn].v)mn=i;
}
// cerr<<mn<<endl;
if(mn==-1)return ;
ans[x][++ans[x][0]]=nd[mn].v;
ban[mn]=true;
// cerr<<"ZZ"<<" "<<x<<" "<<ans[x][1]<<endl;
fo(i,0,n)if(nd[i].bl==x)ok[i]=false;
priority_queue<nod> q;
for(int i=head[mn];i;i=e[i].nxt){
int y=e[i].to;
if(nd[y].bl!=x)continue;
// cerr<<y<<" "<<x<<endl;
cas++;int tmp=cas;
dfs(y,tmp,x,mn,1);
sol(tmp,x,mn);
if(!ans[tmp][0])continue;
q.push(nod{1,tmp});
}
// cerr<<endl;
// cerr<<"W"<<" "<<x<<" "<<f<<endl;
while(!q.empty()){
nod now=q.top();q.pop();
// cerr<<ans[now.id][now.v]<<" "<<now.id<<" "<<now.v<<endl;
ans[x][++ans[x][0]]=ans[now.id][now.v];
if(now.v==ans[now.id][0])continue;
q.push(nod{now.v+1,now.id});
}
// fo(i,1,ans[x][0])cerr<<ans[x][i]<<" ";
// cerr<<endl;
}
signed main(){
freopen("permutation.in","r",stdin);
freopen("permutation.out","w",stdout);
n=cnd=read();
fo(i,1,n){
a[i]=read();
nd[i].v=a[i];
nd[i].tp=1;
nd[i].bl=0;
int now=a[i];
for(int j=2;j*j<=now;j++){
if(now%j==0){
if(!mp[j]){
mp[j]=++cnd;
nd[cnd].v=j;
nd[cnd].tp=0;
nd[cnd].bl=0;
}
add_edg(i,mp[j]);
add_edg(mp[j],i);
}
while(now%j==0)now/=j;
}
if(now!=1){
if(!mp[now]){
mp[now]=++cnd;
nd[cnd].v=now;
nd[cnd].tp=0;
nd[cnd].bl=0;
}
add_edg(i,mp[now]);
add_edg(mp[now],i);
}
}
fo(i,1,cnd){
add_edg(0,i),add_edg(i,0);
ok[i]=true;
}ok[0]=true;
sol(0,0,0);
fo(i,2,n+1)printf("%d ",ans[0][i]);
}
QQ:2953174821