FOI冬令营 Day 3

T1、签到题(sort)

传送门

原题:LOJ 2767

Code

//2019/2/14
//50pts
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
#define MN 1000005
int n,q,a[MN],pw2[35];
int d[MN][35];bool r[MN];
inline void solve()
{
	register int i,j;
	memset(r,0,sizeof r);
	int ret=0;r[n]=true;
	for(i=30;~i;--i)
	{
		int ans=-1;
		for(j=1;j<=n;)
		{
			if(r[j]){++j;continue;}
			int hr=d[j][i],k;
			for(k=j+1;!r[k-1]&&d[k][i]==hr;++k);
			if(r[k-1]){j=k;continue;}
			int tl=d[k][i],l;
			for(l=k+1;!r[l-1]&&d[l][i]==tl;++l);
			if(!r[l-1]) {puts("-1");return;}
			j=l;
			if(hr>tl)
			{
				if(ans==-1) ans=1;
				if(ans==0) {puts("-1");return;}
			}
			else
			{
				if(ans==-1) ans=0;
				if(ans==1) {puts("-1");return;}
			}
			r[k-1]=true;
		}
		if(ans==1) ret+=pw2[i]; 
	}
	printf("%d\n",ret);
}
int main()
{
	freopen("sort.in","r",stdin);
	freopen("sort.out","w",stdout);
	n=read();register int i,S,ans,j;
	pw2[0]=1;
	for(i=1;i<=30;++i) pw2[i]=pw2[i-1]<<1;
	for(i=1;i<=n;++i) a[i]=read();
	for(i=1;i<=n;++i) for(S=a[i],j=0;S>0;++j,S>>=1) d[i][j]=S&1;
	solve();
	q=read();
	register int p,val;
	while(q--)
	{
		p=read();val=read();
		memset(d[p],0,sizeof d[p]);
		for(i=0;val>0;++i,val>>=1) d[p][i]=val&1;
		solve();
	}
	return 0;
}

/*
	只要考虑相邻两行的最高的不相同的位,记录一下每个位的情况即可
	2019/2/14 21:48~22:14
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
#define MN 1000005
int n,q,d[MN][31],f[31][2];
int pw2[31];
inline void add(int x,int y)
{
	register int i;
	for(i=30;~i&&d[x][i]==d[y][i];--i);
	if(i==-1) return;
	++f[i][d[x][i]>d[y][i]];
}
inline void dec(int x,int y)
{
	register int i;
	for(i=30;~i&&d[x][i]==d[y][i];--i);
	if(i==-1) return;
	--f[i][d[x][i]>d[y][i]]; 
}
inline int solve()
{
	register int i,ret=0;
	for(i=0;i<=30;++i)
		if(f[i][0]>0&&f[i][1]>0) return -1;
		else if(f[i][1]>0) ret+=pw2[i];
	return ret;
}
int main()
{
	freopen("sort.in","r",stdin);
	freopen("sort.out","w",stdout);
	n=read();
	register int i,j,S;
	for(pw2[0]=1,i=1;i<=30;++i) pw2[i]=pw2[i-1]<<1;
	for(i=1;i<=n;++i) for(S=read(),j=0;S>0;++j,S>>=1) d[i][j]=S&1;
	q=read();
	for(i=2;i<=n;++i) add(i-1,i);
	printf("%d\n",solve());
	while(q--)
	{
		int pos=read();
		if(pos>1) dec(pos-1,pos);
		if(pos<n) dec(pos,pos+1);
		memset(d[pos],0,sizeof d[pos]);
		for(S=read(),j=0;S>0;++j,S>>=1) d[pos][j]=S&1;
		if(pos>1) add(pos-1,pos);
		if(pos<n) add(pos,pos+1);
		printf("%d\n",solve());
	} 
}

T2、送分题(queue)

原题:LOJ 2734 / 洛谷 如厕计划

传送门

Code

/*
	我们先考虑怎样的序列是满足条件的。
	不难发现,对于男生=女生的情况
	显然每次都是一男一女如厕,充要条件是,对于任何一个后缀,男生<=女生,这很显然
	而对于男生<女生的情况显然是无解的
	对于女生>男生的情况,我们可以把多出来的女生变成男生,使他满足上面的条件
	我们可以从头开始往后扫,只要当前位是女生,且往后的女生>男生,就把这个女生变成男生
	不难发现,满足条件的序列就是,对于任何一个后缀,男生<=女生
	
	换言之,就是从后往前的第i个女生的位置应该在从后往前的第2i个位置之后(不包括第2i个位置)
	从后往前扫,如果当前第i个女生的位置不对,就把她移到第2i个位置上,这样贪心很正确
	假设第i个女生和2i匹配,那么ans=max{Val_i=pos_i-2i}
	
	对每个复读串(设当前的长度为x,女生数为y)分别处理,那么每复读一次,每个女生的 Val值减少2y-x
	所以,如果2y-x>0只需考虑第一个复读串
	如果2y-x<0,只需考虑最后一个复读串
	
	当然如果已经考虑到了第n个女生,之后的女生Val<0,就不用再扫啦
	
	2019/2/14 
	题解写于2019/2/15 12:43 
*/
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
#define MN 100005
std::string s[MN];
ll n,m,l,ans,x[MN];
void solve(std::string &s,int siz)
{
	for(int i=siz;i--;--l)
		if(s[i]=='F'&&n) --n,ans=max(ans,2*n+1-l);
}
int main()
{
	freopen("queue.in","r",stdin);
	freopen("queue.out","w",stdout);
	register int i,j,y;
	n=read(),m=read();l=n<<1;
	for(i=1;i<=m;++i) std::cin>>s[i],x[i]=read();
	for(i=m;i;--i)
	{
		register int siz=s[i].size();
		for(j=y=0;j<siz;++j) y+=s[i][j]=='F';
		if((y<<1)-siz>=0)
		{
			solve(s[i],siz);
			l-=(x[i]-1)*siz;n-=(x[i]-1)*y;
			if(n<=0)break;
		}
		else
		{
			l-=(x[i]-1)*siz;n-=(x[i]-1)*y;
			solve(s[i],siz);
			if(n<=0) break; 
		}
	}
	return 0*printf("%lld\n",n>0?-1:ans);
}

T3、简单题(game)

传送门

原题:LOJ 2731

Code

咕咕咕

Blog来自PaperCloud,未经允许,请勿转载,TKS!

posted @ 2019-02-15 22:06  PaperCloud  阅读(421)  评论(0编辑  收藏  举报