Educational Codeforces Round 82 (Rated for Div. 2)

前面题看了懒得写了 直接从D开始

D.Fill The Bag

题解

贪心,用\(have[i]\) 数组记录\(2^i\) 有多少个,然后对于这个\(n\) ,从最低位开始处理,因为每一位最多只需要1个,那么当前有的我们直接用上即可,剩下没有用上的,我们把\(2^i\) 合并到\(2^{i+1}\) 去,注意个数要除以2.如果对于当前位没有1的,那我们只能通过往后找数,拆分来获得这个数了,很显然拆离他最近的那个数最优,在拆的时候,比如我们要拆\(2^j\) ,目前需要\(2^i\) ,在过程中会产生\(2^{j-1},2^{j-2},...,2^{i+1}\) ,都要相应的加上。

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline LL read()
{
	LL x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
	return x*f;
}
int T,m,have[70];
LL n,t,sum;
int main()
{
	T=read();
	while(T--)
	{
		mem(have,0);
		n=read();m=read();
		LL ans=0; sum=0;
		for(int i=1;i<=m;i++)
		{
			t=read();
			sum+=t;
			int cnt=-1;
			while(t)cnt++,t>>=1;
			have[cnt]++;
		}
		if(sum<n)
		{
			printf("-1\n");
			continue;
		}
		int i=0;
		while(n)
		{
			if(n&1ll)
			{ 
				if(have[i])have[i]--;
				else
				{
					for(int j=i+1;j<60;j++)
						if(have[j])
						{
							have[j]--;
							while(j>i)have[--j]++,ans++;
							break;
						}
				}
			}
			have[i+1]+=have[i]/2;
			n>>=1ll;i++;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

Erase Subsequences

题解

shit为什么我写的题解全没了!!!!

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
	return x*f;
}
const int maxl=410;
int T;
char s[maxl],t[maxl];
int dp[maxl][maxl];
int main()
{
	T=read();
	while(T--)
	{
		scanf("%s%s",s+1,t+1);
		int l1=strlen(s+1),l2=strlen(t+1);
		bool ok=0;
		for(int k=1;k<=l2 && !ok;k++)//第一段范围1~k,第二段k+1~l2 
		{
			mem(dp,-1);//dp[i][j]表示s匹配到i,第一段匹配到j时候第二段的最远匹配
			for(int i=0;i<=l1;i++)dp[i][0]=0;
			for(int i=0;i<l1;i++)
				for(int j=0;j<=k;j++) 
				{
					if(dp[i][j]==-1)continue;
					dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
					if(s[i+1]==t[j+1])dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j]);
					if(s[i+1]==t[dp[i][j]+1+k])dp[i+1][j]=max(dp[i+1][j],dp[i][j]+1); 
				}
			for(int i=0;i<=l1;i++)if(dp[i][k]==l2-k)ok=1;
		}
		if(!ok)printf("NO\n");
		else printf("YES\n");		
	}
	return 0;
}

Number of Components

题解

这道题题目限制有一些神奇,我们可以从题目限制出手。
首先

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
	return x*f;
}
const int maxn=310;
int n,m,Q,a[maxn][maxn],f[maxn*maxn],x,y,c,all,dx[4]={0,1,0,-1},dy[4]={1,0,-1,0},ans[2000010];
bool legal(int x,int y){return x>=0 && x<n && y>=0 && y<m;}
vector<PII> add[2000010],del[2000010]; 
int getf(int x){return f[x]==x ? x : f[x]=getf(f[x]);}
bool merge(int x,int y)
{
	int a=getf(x),b=getf(y);
	return a!=b ? f[a]=b,true : false;
}
void calc(vector<PII> &col,int t)
{
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)a[i][j]=0,f[i*m+j]=i*m+j;
	for(auto it: col)
	{
		x=it.X/m,y=it.X%m;
		a[x][y]=1;
		int block=1;
		for(int i=0;i<4;i++)
		{
			int nx=x+dx[i],ny=y+dy[i];
			if(legal(nx,ny) && a[nx][ny]==1)
				block-=merge(x*m+y,nx*m+ny);
		}
		if(it.Y==Q+1)ans[it.Y]+=t*block;
	}
}
int main()
{
	n=read();m=read();Q=read();
	for(int i=1;i<=Q;i++)
	{
		x=read()-1;y=read()-1;c=read();
		int pos=x*m+y;
		if(i==Q)all=c; 
		add[c].push_back(make_pair(pos,i));
		del[a[x][y]].push_back(make_pair(pos,i));
		a[x][y]=c;
	}
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++)
			del[a[i][j]].push_back(make_pair(i*m+j,Q+1));
	for(int i=0;i<=all;i++)reverse(del[i].begin(),del[i].end()); 
	for(int i=1;i<=all;i++)calc(add[i],1);
	for(int i=0;i<=all;i++)calc(del[i],-1);
	for(int i=1,tmp=1;i<=Q;i++)tmp+=ans[i],printf("%d\n",tmp);
	return 0;
}

废话

做2600以上太困难了...

posted @ 2020-02-18 23:18  小飞淙的云端  阅读(51)  评论(0编辑  收藏