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以上太困难了...