Codeforces 863 简要题解

时间:2023-03-08 16:09:34
Codeforces 863 简要题解

文章目录

传送门

简要题解?因为最后一题太毒不想写了所以其实是部分题解。。。

A题

传送门

题意简述:给你一个数,问你能不能通过加前导000使其成为一个回文数。


思路:直接模拟。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
int cnt[10];
char s[20];
int main(){
	scanf("%s",s+1);
	int l=1,r=strlen(s+1);
	while(s[l]=='0'&&l!=r)++l;
	if(l==r)return puts("YES"),0;
	while(s[r]=='0')--r;
	while(l<r){
		if(s[l]!=s[r])return puts("NO"),0;
		++l,--r;
	}
	puts("YES");
	return 0;
}

B题

传送门

题意:有2n2n2n个人坐船,每个人有重量,n−1n-1n−1艘双人船和222艘单人船,双人船的代价是乘坐的两个人重量差的绝对值,问所有人坐上船的最小代价。


思路:枚举哪两个坐单人船暴力更新答案。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int N=1055;
int n,w[N],a[N],ans=0x3f3f3f3f;
inline void solve(){
	int sum=0;
	for(ri i=1;i<=n*2-2;i+=2)sum+=a[i+1]-a[i];
	ans=min(ans,sum);
}
int main(){
	n=read();
	for(ri i=1;i<=n*2;++i)w[i]=read();
	sort(w+1,w+n*2+1);
	for(ri i=1;i<=n*2;++i){
		for(ri j=i+1;j<=n*2;++j){
			int tot=0;
			for(ri k=1;k<=n*2;++k)if(k!=i&&k!=j)a[++tot]=w[k];
			solve();
		}
	}
	cout<<ans;
	return 0;
}

C题

传送门

题意:两个机器人猜拳,出拳可能为1,2,31,2,31,2,3中的一个,当局面为(i,j)(i,j)(i,j)时AAA下一轮会出Ai,jA_{i,j}Ai,j​,BBB下一轮会出Bi,jB_{i,j}Bi,j​,问最后两个机器人的积分。


思路:显然出拳序列是一个ρ\rhoρ型的,把环找出来即可。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
typedef pair<int,int> pii;
typedef long long ll;
const int N=1055;
vector<pii>turn;
vector<pii>sum;
ll k;
int a,b;
pii trans[4][4];
map<pii,int>vis;
inline int check(int a,int b){
	if(a==2&&b==1)return 1;
	if(a==3&&b==2)return 1;
	if(a==1&&b==3)return 1;
	return 0;
}
int main(){
	scanf("%lld",&k),a=read(),b=read();
	for(ri i=1;i<=3;++i)for(ri j=1;j<=3;++j)trans[i][j].fi=read();
	for(ri i=1;i<=3;++i)for(ri j=1;j<=3;++j)trans[i][j].se=read();
	turn.push_back(pii(0,0)),sum.push_back(pii(0,0));
	turn.push_back(pii(a,b)),sum.push_back(pii(check(a,b),check(b,a)));
	for(ri i=1;i<k;++i){
		pii tmp=turn[i],nxt=trans[tmp.fi][tmp.se],pts=sum[i];
		vis[tmp]=i;
		if(vis[nxt]){
			int tim=vis[nxt],len=i-tim+1,ttmp=(k-tim+1)%len;
			pii ans=sum[tim-1+ttmp];
			ll a1=ans.fi,a2=ans.se;
			a1+=(k-tim+1)/len*(pts.fi-sum[tim-1].fi),a2+=(k-tim+1)/len*(pts.se-sum[tim-1].se);
			cout<<a1<<' '<<a2;
			return 0;
		}
		turn.push_back(nxt),sum.push_back(pii(pts.fi+check(nxt.fi,nxt.se),pts.se+check(nxt.se,nxt.fi)));
	}
	cout<<sum[k].fi<<' '<<sum[k].se<<'\n';
	return 0;
}

D题

传送门

题意:给一个序列,支持区间右移,区间翻转,问最后的序列。


思路:加强版文艺平衡树。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int N=4e5+5;
typedef pair<int,int> pii;
int n,m,q;
namespace bst{
	#define lc (son[p][0])
	#define rc (son[p][1])
	int val[N],rd[N],siz[N],rev[N],rt=0,tot=0,son[N][2];
	inline int build(int v){return val[++tot]=v,rd[tot]=rand(),siz[tot]=1,son[tot][0]=son[tot][1]=0,tot;}
	inline void pushup(int p){siz[p]=siz[lc]+1+siz[rc];}
	inline void pushnow(int p){rev[p]^=1,swap(son[p][0],son[p][1]);}
	inline void pushdown(int p){
		if(!rev[p])return;
		if(lc)pushnow(lc);
		if(rc)pushnow(rc);
		rev[p]=0;
	}
	inline int merge(int a,int b){
		if(!a||!b)return a+b;
		pushdown(a),pushdown(b);
		if(rd[a]>rd[b])return son[a][1]=merge(son[a][1],b),pushup(a),a;
		return son[b][0]=merge(a,son[b][0]),pushup(b),b;
	}
	inline pii split(int p,int k){
		if(!p)return pii(0,0);
		pii tmp;
		pushdown(p);
		if(siz[lc]>=k)return tmp=split(lc,k),lc=tmp.se,pushup(p),pii(tmp.fi,p);
		return tmp=split(rc,k-siz[lc]-1),rc=tmp.fi,pushup(p),pii(p,tmp.se);
	}
	inline void insert(int id,int v){
		pii x=split(rt,id-1);
		rt=merge(merge(x.fi,build(v)),x.se);
	}
	inline void delet(int id){
		pii x=split(rt,id-1),y=split(x.se,1);
		rt=merge(x.fi,y.se);
	}
	inline int query(int id){
		pii x=split(rt,id-1),y=split(x.se,1);
		int ret=val[y.fi];
		return rt=merge(x.fi,merge(y.fi,y.se)),ret;
	}
	inline void update(int l,int r){
		pii x=split(rt,l-1),y=split(x.se,r-l+1);
		pushnow(y.fi),rt=merge(x.fi,merge(y.fi,y.se));
	}
	#undef lc
	#undef rc
}
int main(){
	srand(time(NULL));
	n=read(),q=read(),m=read();
	for(ri i=1;i<=n;++i)bst::insert(i,read());
	while(q--){
		int op=read(),l=read(),r=read();
		if(op==1){
			int tmp=bst::query(r);
			bst::delet(r);
			bst::insert(l,tmp);
		}
		else bst::update(l,r);
	}
	for(ri i=1;i<=n;++i)cerr<<bst::query(i)<<' ';
	puts("");
	for(ri i=1;i<=m;++i)cout<<bst::query(read())<<' ';
	return 0;
}

E题

传送门

题意:给一些线段,输出任意一条满足以下条件的线段:

去掉它之后覆盖的总长度不变。


思路:离散化之后差分/线段树。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int N=6e5+5;
int n,m=0,val[N];
struct node{int l,r;}a[N];
namespace SGT{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (l+r>>1)
	int mn[N<<2],add[N<<2];
	inline void pushup(int p){mn[p]=min(mn[lc],mn[rc]);}
	inline void pushnow(int p,int v){mn[p]+=v,add[p]+=v;}
	inline void pushdown(int p){if(add[p])pushnow(lc,add[p]),pushnow(rc,add[p]),add[p]=0;}
	inline void update(int p,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr)return pushnow(p,1);
		pushdown(p);
		if(qr<=mid)update(lc,l,mid,ql,qr);
		else if(ql>mid)update(rc,mid+1,r,ql,qr);
		else update(lc,l,mid,ql,mid),update(rc,mid+1,r,mid+1,qr);
		pushup(p);
	}
	inline int query(int p,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr)return mn[p];
		pushdown(p);
		if(qr<=mid)return query(lc,l,mid,ql,qr);
		if(ql>mid)return query(rc,mid+1,r,ql,qr);
		return min(query(lc,l,mid,ql,mid),query(rc,mid+1,r,mid+1,qr));
	}
}
int main(){
	n=read();
	for(ri i=1;i<=n;++i)val[++m]=a[i].l=read(),val[++m]=a[i].r=read(),val[++m]=a[i].l-1;
	sort(val+1,val+m+1),m=unique(val+1,val+m+1)-val-1;
	for(ri i=1;i<=n;++i){
		a[i].l=lower_bound(val+1,val+m+1,a[i].l)-val;
		a[i].r=lower_bound(val+1,val+m+1,a[i].r)-val;
		SGT::update(1,1,m,a[i].l,a[i].r);
	}
	for(ri i=1;i<=n;++i)if(SGT::query(1,1,m,a[i].l,a[i].r)>1)return cout<<i,0;
	puts("-1");
	return 0;
}

F题

传送门

题意:

现在有nnn个数,mmm个限制。每个数只能为111到nnn,限制表示为一个区间中所有数不小于/不大于某个数,最后的代价是∑i=1ncnti2\sum_{i=1}^ncnt_i^2∑i=1n​cnti2​,问最小代价。


思路:直接按照题意模拟跑费用流。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int N=205,M=100005;
int n,m,up[N],down[N];
namespace mcmf{
	int d[N],first[N],pred[N],pos[N],F,s,t,cnt;
	bool in[N];
	struct edge{int v,next,c,w;}e[M];
	inline void addedge(int u,int v,int c,int w){e[++cnt]=(edge){v,first[u],c,w},first[u]=cnt;}
	inline void add(int u,int v,int c,int w){cerr<<u<<' '<<v<<' '<<c<<' '<<w<<'\n',addedge(u,v,c,w),addedge(v,u,0,-w);}
	inline void init(){cnt=-1,memset(first,-1,sizeof(first)),F=0,s=0,t=2*n+1;}
	inline bool bfs(){
		static int q[N],hd,tl;
		for(ri i=s;i<=t;++i)d[i]=0x3f3f3f3f;
		d[q[hd=tl=1]=s]=0;
		while(hd<=tl){
			int x=q[hd++];
			in[x]=0;
			for(ri i=first[x],v;~i;i=e[i].next){
				if(e[i].c&&d[v=e[i].v]>d[x]+e[i].w){
					d[v]=d[x]+e[i].w,pred[v]=x,pos[v]=i;
					if(!in[v])in[q[++tl]=v]=1;
				}
			}
		}
		if(d[t]==0x3f3f3f3f)return 0;
		int p=t;
		F+=d[t];
		while(p^s)--e[pos[p]].c,++e[pos[p]^1].c,p=pred[p];
		return 1;
	}
}
int main(){
	n=read(),m=read();
	mcmf::init();
	for(ri i=1;i<=n;++i){
		up[i]=n,down[i]=1;
		for(ri j=1;j<=n;++j)mcmf::add(mcmf::s,i,1,j*j-(j-1)*(j-1));
		mcmf::add(i+n,mcmf::t,1,0);
	}
	for(ri t,l,r,v,tt=1;tt<=m;++tt){
		t=read(),l=read(),r=read(),v=read();
		if(t==1)for(ri i=l;i<=r;++i)down[i]=max(down[i],v);
		else for(ri i=l;i<=r;++i)up[i]=min(up[i],v);
	}
	for(ri i=1;i<=n;++i){
		if(up[i]<down[i])return puts("-1"),0;
		for(ri j=down[i];j<=up[i];++j)mcmf::add(j,i+n,1,0);
	}
	while(mcmf::bfs());
	cout<<mcmf::F;
	return 0;
}

G题

传送门

咕咕咕