Codeforces Round #135 (Div. 2) http://codeforces.com/contest/219
cf 再次悲剧了……11:30 开始,寝室早就断电了,只能靠笔记本电池艰难地维持那么一个多小时,而且没有灯,也不能再草稿纸上演算真心累呀……结果这次cf只A了前两个题目结尾,而且其中有个题目还不是1A,……
A k-String
水题,随便yy下就行了,当每个字符出现的次数都是k的倍数的时候存在满足条件的字符串
这个题目还是比较有意思的题目,要多想会儿。
题意: 给出 p 和 d ,要求 [ p-d , p] 这个区间范围内找包含末尾包含9的个数最多的数,如果多个数满足条件那么就找最大的那
思路: 我是枚举要找的末尾9的个数,然后再贪心找离p最近的数(这样的数只有一个),取最后值即可
个。
这个题题意都不讲了,比赛的时候就是卡在这个题目上了,贪心dp都可以
dp做法:dp[ len [k ] 表示 把第len个数涂成k眼色前len块满足条件的最优解,即最少图的次数
贪心做法 , 不过我确实不怎么会证明为什么这样做就会ac,是我自己瞎yy出来的,贪心做法要快很多
如果做个跟这个类似的题目的话,直接就是水题了,两次dfs 即可,还有没有太坑爹没有爆栈
线段树的区间和并,蛋疼,调试了我好长时间,不知道wa了多少次,太弱了
水题,随便yy下就行了,当每个字符出现的次数都是k的倍数的时候存在满足条件的字符串
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
char s[1010];
int cnt[100];
int main()
{
int k;
while(cin>>k>>s)
{
int len=strlen(s);
for(int i=0;i<len;i++)
cnt[s[i]-'a']++;
bool ok=1;
for(int i=0;i<26&&ok;i++)
if(cnt[i]%k!=0) ok=0;
if(ok)
{
string s="";
for(int i=0;i<26;i++)
if(cnt[i])
{
for(int j=0;j<cnt[i]/k;j++)
s+=(char)('a'+i);
}
while(k--)
cout<<s;
cout<<endl;
}
else puts("-1");
}
return 0;
}
B |
题意: 给出 p 和 d ,要求 [ p-d , p] 这个区间范围内找包含末尾包含9的个数最多的数,如果多个数满足条件那么就找最大的那
思路: 我是枚举要找的末尾9的个数,然后再贪心找离p最近的数(这样的数只有一个),取最后值即可
个。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int main()
{
ll a,b;
while(cin>>a>>b)
{
ll cnt=0,ans=0,d=a;
while(d) cnt++,d/=10;
for(ll i=1,x=10;i<=cnt;i++,x*=10)
{
if(x-1>a) break;
ll rest=a%x,dd=a/x;
ll tmp;
if(rest==x-1) tmp=dd*x+x-1;
else tmp=(dd-1)*x+x-1;
if(tmp<a-b) break;
ans=tmp;
}
if(ans) cout<<ans<<endl;
else cout<<a<<endl;
}
return 0;
}
C |
dp做法:dp[ len [k ] 表示 把第len个数涂成k眼色前len块满足条件的最优解,即最少图的次数
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define maxn 500010
#define inf 0x3fffffff
char s[maxn];
int n,k,dp[maxn][26];
void dfs(int id,int d,int pre)
{
if(id<0) return;
for(int i=0;i<k;i++)
if(dp[id][i]==d&&i!=pre)
{
dfs(id-1,d- (i!=s[id]),i);
putchar(i+'A');
break;
}
}
int main()
{
while(scanf("%d%d",&n,&k)==2)
{
scanf("%s",s);
for(int i=0;i<n;i++) s[i]-='A';
for(int i=1;i<n;i++)
for(int j=0;j<k;j++) dp[i][j]=inf;
for(int j=0;j<k;j++) dp[0][j]= (j!=s[0]);
for(int i=1;i<n;i++)
for(int j=0;j<k;j++)
for(int r=0;r<k;r++)
if(j!=r) dp[i][j]=min(dp[i][j],dp[i-1][r]+(s[i]!=j));
int Min=dp[n-1][0];
for(int i=1;i<k;i++) Min=min(Min,dp[n-1][i]);
printf("%d\n",Min);
/* for(int i=0;i<n;i++)
{
for(int j=0;j<k;j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}*/
dfs(n-1,Min,-1);
puts("");
}
return 0;
}
贪心做法 , 不过我确实不怎么会证明为什么这样做就会ac,是我自己瞎yy出来的,贪心做法要快很多
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int inf=0x3fffffff;
char s[500010];
int dp[500010][30];
int len,k;
void change(char &cc,char a,char b)
{
for(int i=0;i<k;i++)
if(i+'A'!=a&&i+'A'!=b) { cc=i+'A';break; }
}
int main()
{
while(scanf("%d%d",&len,&k)==2)
{
scanf("%s",s);
int t=0;
if(k==2)
{
int t1=0,t2=0;
for(int i=0;i<len;i++)
if(s[i]!=i%2+'A') t1++;
for(int i=0;i<len;i++)
if(s[i]!=(i+1)%2+'A') t2++;
if(t1>t2){
printf("%d\n",t2);
for(int i=0;i<len;i++) putchar((i+1)%2+'A');
puts("");
}else{
printf("%d\n",t1);
for(int i=0;i<len;i++) putchar(i%2+'A');
puts("");
}
continue;
}
for(int i=0;i<len;i++)
if(i+1<len&&s[i]==s[i+1])
t++,change(s[i+1],s[i],s[i+2]);
printf("%d\n%s\n",t,s);
}
return 0;
}
E |
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=500010;
int dp[maxn];
vector<pair<int,bool> > g[maxn];
vector<int> ans;
int Min1(int &a,int b)
{
if(a>b)
{
a=b;return 1;
}
return 0;
}
void dfs(int u,int fa)
{
int sz=g[u].size();
for(int i=0;i<sz;i++)
{
int v=g[u][i].first;
bool ok=g[u][i].second;
if(v==fa) continue;
dfs(v,u);
dp[u]+=dp[v]+ok;
}
}
void dfs1(int u,int fa)
{
int sz=g[u].size();
for(int i=0;i<sz;i++)
{
int v=g[u][i].first;
bool ok=g[u][i].second;
if(v==fa) continue;
dp[v]=dp[u]+ (ok?-1:1);
dfs1(v,u);
}
}
int main()
{
int n,a,b;
while(scanf("%d",&n)==1)
{
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
g[a].push_back(make_pair(b,0));
g[b].push_back(make_pair(a,1));
}
memset(dp,0,sizeof(dp));
dfs(1,-1);
dfs1(1,-1);
int Min=dp[1];
for(int i=1;i<=n;i++)
Min1(Min,dp[i]),g[i].clear();
for(int i=1;i<=n;i++)
if(Min==dp[i]) ans.push_back(i);
printf("%d\n%d",Min,ans[0]);
for(int i=1;i<ans.size();i++)
printf(" %d",ans[i]);
puts("");
ans.clear();
}
return 0;
}
E |
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 200010
int lsum[maxn<<2],msum[maxn<<2],rsum[maxn<<2],ans[1000001];
void pushup(int rt,int l)
{
lsum[rt]=lsum[rt<<1];
if(lsum[rt<<1]==l-l/2) lsum[rt]+=lsum[rt<<1|1];
rsum[rt]=rsum[rt<<1|1];
if(rsum[rt<<1|1]==l/2) rsum[rt]+=rsum[rt<<1];
msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);
}
void build(int l,int r,int rt)
{
lsum[rt]=msum[rt]=rsum[rt]=r-l+1;
if(l==r) return;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int p,int val,int l,int r,int rt)
{
if(l==r)
{
lsum[rt]=msum[rt]=rsum[rt]=val;
return;
}
int m=(l+r)>>1;
if(p<=m) update(p,val,lson);
else update(p,val,rson);
pushup(rt,r-l+1);
}
int query(int p,int l,int r,int rt)
{
if(l==r) return l;
int m=(l+r)>>1;
if(msum[rt<<1]>=p) return query(p,lson);
else if(rsum[rt<<1]+lsum[rt<<1|1]>=p) return query(p-rsum[rt<<1],rson);
else return query(p,rson);
}
int main()
{
int n,m,id,a;
while(scanf("%d%d",&n,&m)==2)
{
build(1,n,1);
// update(6,0,1,n,1);
while(m--)
{
scanf("%d%d",&id,&a);
if(id==1)
{
int Max=max(lsum[1],max((msum[1]+1)/2,rsum[1])),np;
if(Max==lsum[1]) np=1;
else if((msum[1]+1)/2==Max)
{
if(msum[1]%2==0)
np=query(msum[1]-1,1,n,1)-msum[1]/2+1;
else np=query(msum[1],1,n,1)-msum[1]/2;
}else np=n;
update(np,0,1,n,1);
printf("%d\n",np);
ans[a]=np;
}
else update(ans[a],1,1,n,1);
}
}
return 0;
}