codeforces contest 349
2016-12-12 15:32
323 查看
http://codeforces.com/contest/349
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
B 349B Color
the Fence
题意:有v升颜料,涂1~9所花费的颜料是a[i],求涂成的数字最大
题解:大家都用贪心,只有我用背包,我好可怜啊。
解法一:完全背包
肯定是能涂数字越多越好,然后再越大越好。所以花费就是a[i],价值是1。
然后要标记路径。对于两种一样的方案,要维护数字比较大的方案。
解法二:贪心
先求出肯定能取cnt个。然后对于取的每一个,贪心的取最大的,如果取该个能保证总共输出的够cnt个,那么就可以取。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int V=1000005;
int a[15],d[V],ans[15],mrk[V];
void dfs(int v) {
if(v<=0||mrk[v]==-1) return ;
++ans[mrk[v]];
dfs(v-a[mrk[v]]);
}
int main() {
int v;
while(~scanf("%d",&v)) {
for(int i=1;i<=9;++i) scanf("%d",&a[i]);
//比它小,花费还一样
for(int i=1;i<=9;++i) {
for(int j=i+1;j<=9;++j) {
if(a[j]==a[i]) {
a[i]=v+1;
break;
}
}
}
memset(d,0,sizeof(d));
memset(mrk,-1,sizeof(mrk));
for(int i=1;i<=9;++i) {
for(int j=a[i];j<=v;++j) {
if(d[j-a[i]]+1>d[j]) {
d[j]=d[j-a[i]]+1;
mrk[j]=i;
} else if(d[j-a[i]]+1==d[j]&&i>mrk[j]) {
mrk[j]=i;
}
}
}
if(d[v]==0) {
puts("-1");
continue;
}
memset(ans,0,sizeof(ans));
dfs(v);
for(int i=9;i>=1;--i) {
for(int j=1;j<=ans[i];++j) {
printf("%d",i);
}
}
puts("");
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
C 348A Mafia
题意:n个人,第i个人最少要当a[i]次玩家。每场比赛有一个裁判,其他人都是玩家。求最少比赛次数。
题解:我好像是猜的啊??我真的好菜。
1,最少要比ans1=max(a[i])场。
2,接下来我们用集合来理解a数组。
一共有n个集合(n个人),第i个集合中最少有a[i]个元素(比赛)。
集合可以重合,但是因为不可能有n个人同时参加一场比赛,所以一个元素最多属于n-1个集合。
按照贪心的想法就是ans2=sum(a[i])/(n-1)
然后取max(ans1,ans2)就行了
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
ll a[100005];
int main() {
int n;
while(~scanf("%d",&n)) {
ll ans1=0,ans2=0;
for(int i=1;i<=n;++i) {
scanf("%I64d",&a[i]);
ans1=max(a[i],ans1);
ans2=ans2+a[i];
}
if(ans2%(n-1)) {
ans2=ans2/(n-1)+1;
} else {
ans2=ans2/(n-1);
}
printf("%I64d\n",max(ans1,ans2));
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
D 348B Apple
Tree
题意:有一棵树,它的所有儿子的权重必须相等。权重的定义:叶节点有点权,其余节点的权重等于它的儿子的权重之和。
题解:好像就是一层一层推上去(太早之前做的了,有点忘)。54行去掉会wa,不知道为何。
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
E 348C Subset
Sums
题意:n个数,m个集合,q次操作。
"? k" :查询第k个集合的元素和
"+ k x" : 第k个集合每个元素加上x
题解:我好像还是第一次做分块的题目。
把集合分成大集合(大小大于SQRTN,个数肯定小于SQRTN个(因为集合大小之和是n))和小集合。
总思想就是每个大集合维护sum,add值,小集合暴力。这样每次查询的复杂度是sqrtN
大集合+:sum+=x
小集合+:暴力的每个去加,还要更新大集合的add
大集合?:sum,add
小集合?:暴力的每个去加,还要考虑大集合的add对他的影响
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
B 349B Color
the Fence
题意:有v升颜料,涂1~9所花费的颜料是a[i],求涂成的数字最大
题解:大家都用贪心,只有我用背包,我好可怜啊。
解法一:完全背包
肯定是能涂数字越多越好,然后再越大越好。所以花费就是a[i],价值是1。
然后要标记路径。对于两种一样的方案,要维护数字比较大的方案。
解法二:贪心
先求出肯定能取cnt个。然后对于取的每一个,贪心的取最大的,如果取该个能保证总共输出的够cnt个,那么就可以取。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
const int V=1000005;
int a[15],d[V],ans[15],mrk[V];
void dfs(int v) {
if(v<=0||mrk[v]==-1) return ;
++ans[mrk[v]];
dfs(v-a[mrk[v]]);
}
int main() {
int v;
while(~scanf("%d",&v)) {
for(int i=1;i<=9;++i) scanf("%d",&a[i]);
//比它小,花费还一样
for(int i=1;i<=9;++i) {
for(int j=i+1;j<=9;++j) {
if(a[j]==a[i]) {
a[i]=v+1;
break;
}
}
}
memset(d,0,sizeof(d));
memset(mrk,-1,sizeof(mrk));
for(int i=1;i<=9;++i) {
for(int j=a[i];j<=v;++j) {
if(d[j-a[i]]+1>d[j]) {
d[j]=d[j-a[i]]+1;
mrk[j]=i;
} else if(d[j-a[i]]+1==d[j]&&i>mrk[j]) {
mrk[j]=i;
}
}
}
if(d[v]==0) {
puts("-1");
continue;
}
memset(ans,0,sizeof(ans));
dfs(v);
for(int i=9;i>=1;--i) {
for(int j=1;j<=ans[i];++j) {
printf("%d",i);
}
}
puts("");
}
return 0;
}
#include<cstdio> #include<algorithm> using namespace std; int a[15]; int main() { int v; while(~scanf("%d",&v)) { int zuixiao=100000; for(int i=1;i<=9;++i) { scanf("%d",&a[i]); zuixiao=min(zuixiao,a[i]); } int cnt=v/zuixiao; if(cnt==0) { puts("-1"); continue; } for(int i=cnt-1;i>=0;--i) {//还要涂i个 for(int j=9;j>=1;--j) { if(v>=a[j]&&(v-a[j])/zuixiao>=i) { printf("%d",j); v-=a[j]; } } } puts(""); } return 0; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
C 348A Mafia
题意:n个人,第i个人最少要当a[i]次玩家。每场比赛有一个裁判,其他人都是玩家。求最少比赛次数。
题解:我好像是猜的啊??我真的好菜。
1,最少要比ans1=max(a[i])场。
2,接下来我们用集合来理解a数组。
一共有n个集合(n个人),第i个集合中最少有a[i]个元素(比赛)。
集合可以重合,但是因为不可能有n个人同时参加一场比赛,所以一个元素最多属于n-1个集合。
按照贪心的想法就是ans2=sum(a[i])/(n-1)
然后取max(ans1,ans2)就行了
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <string>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define de(x) cout << #x << "=" << x << endl
ll a[100005];
int main() {
int n;
while(~scanf("%d",&n)) {
ll ans1=0,ans2=0;
for(int i=1;i<=n;++i) {
scanf("%I64d",&a[i]);
ans1=max(a[i],ans1);
ans2=ans2+a[i];
}
if(ans2%(n-1)) {
ans2=ans2/(n-1)+1;
} else {
ans2=ans2/(n-1);
}
printf("%I64d\n",max(ans1,ans2));
}
return 0;
}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
D 348B Apple
Tree
题意:有一棵树,它的所有儿子的权重必须相等。权重的定义:叶节点有点权,其余节点的权重等于它的儿子的权重之和。
题解:好像就是一层一层推上去(太早之前做的了,有点忘)。54行去掉会wa,不知道为何。
#include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <string> #include <cmath> #include <queue> #include <set> #include <map> using namespace std; typedef long long ll; #define de(x) cout << #x << "=" << x << endl const int N=100005; int a ,last ,sz; struct Edge { int pre,to; }e[2*N]; void inite() { sz=0; memset(last,-1,sizeof(last)); } void adde(int u,int v) { e[++sz].to=v; e[sz].pre=last[u]; last[u]=sz; } struct Node { ll napp;//这个分支的总苹果数 ll d;//napp|d }node ; ll gcd(ll a,ll b) { if(b==0) return a; return gcd(b,a%b); } ll lcm(ll a,ll b) { return a*b/gcd(a,b); } void dfs(int fa,int u) { ll mapp=-1;//儿子中最少的苹果 ll dlcm=1;//儿子的d的lcm ll nson=0;//儿子个数 for(int i=last[u];i!=-1;i=e[i].pre) { if(e[i].to==fa) continue; dfs(u,e[i].to); if(mapp==-1) { mapp=node[e[i].to].napp; } else { mapp=min(mapp,node[e[i].to].napp); } dlcm=lcm(dlcm,node[e[i].to].d); ++nson; } if(dlcm==0) dlcm=1; if(nson==0) {//叶子节点 node[u].napp=a[u]; node[u].d=1; } else { node[u].napp=mapp/dlcm*dlcm*nson; node[u].d=dlcm*nson; } } int main() { int n; while(~scanf("%d",&n)) { ll sum=0;//总共有几个苹果 for(int i=1;i<=n;++i) { scanf("%d",&a[i]); sum=sum+a[i]; } int u,v;inite(); for(int i=1;i<n;++i) { scanf("%d%d",&u,&v); adde(u,v); adde(v,u); } memset(node,0,sizeof(node)); dfs(1,1); printf("%I64d\n",sum-node[1].napp); } return 0; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
E 348C Subset
Sums
题意:n个数,m个集合,q次操作。
"? k" :查询第k个集合的元素和
"+ k x" : 第k个集合每个元素加上x
题解:我好像还是第一次做分块的题目。
把集合分成大集合(大小大于SQRTN,个数肯定小于SQRTN个(因为集合大小之和是n))和小集合。
总思想就是每个大集合维护sum,add值,小集合暴力。这样每次查询的复杂度是sqrtN
大集合+:sum+=x
小集合+:暴力的每个去加,还要更新大集合的add
大集合?:sum,add
小集合?:暴力的每个去加,还要考虑大集合的add对他的影响
#include<cstdio> #include<vector> #include<cstring> using namespace std; typedef long long ll; const int N=100005; const int SQRTN=317; ll a ,sum[SQRTN],add[SQRTN]; int sz ,da ,mrk ,jiaoji[SQRTN] ,tmp ; vector<int> S ; int main() { int n,m,q; scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=n;++i) scanf("%I64d",&a[i]); int szda=0; for(int i=1;i<=m;++i) { scanf("%d",&sz[i]); int x; for(int j=1;j<=sz[i];++j) { scanf("%d",&x); S[i].push_back(x); } if(sz[i]>=SQRTN) { da[++szda]=i; mrk[i]=1; for(int j=0;j<sz[i];++j) { int t=S[i][j]; add[szda]=add[szda]+a[t]; } } } for(int i=1;i<=szda;++i) { int ii=da[i];//第ii个集合是大集合 memset(tmp,0,sizeof(tmp)); for(int j=0;j<sz[ii];++j) tmp[S[ii][j]]=1; for(int j=1;j<=m;++j) { for(int k=0;k<sz[j];++k) { jiaoji[i][j]+=tmp[S[j][k]]; } } } char op;int k,x; while(q--) { scanf(" %c %d",&op,&k); if(op=='+') { scanf("%d",&x); if(mrk[k]) {//大集合 int kk; for(int i=1;i<=szda;++i) { if(da[i]==k) { kk=i; break; } } sum[kk]+=0ll+x; } else { for(int i=0;i<sz[k];++i) a[S[k][i]]+=0ll+x; for(int i=1;i<=szda;++i) { add[i]+=1ll*x*jiaoji[i][k]; } } } else { if(mrk[k]) { int kk; for(int i=1;i<=szda;++i) { if(da[i]==k) { kk=i; break; } } ll ans=sum[kk]*sz[k]+add[kk]; for(int i=1;i<=szda;++i) { if(i==kk) continue; ans+=sum[i]*jiaoji[i][k]; } printf("%I64d\n",ans); } else { ll ans=0; for(int i=0;i<sz[k];++i) ans+=a[S[k][i]]; for(int i=1;i<=szda;++i) { ans+=sum[i]*jiaoji[i][k]; } printf("%I64d\n",ans); } } } return 0; }
相关文章推荐
- Codeforces April Fools Contest 2017
- codeforces 730G Car Repair Shop 2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest
- CodeForces - 725D Contest Balloons 贪心
- CodeForces 589J ——2015-2016 ACM-ICPC, NEERC, Southern Subregional Contest
- Codeforces 730 J. Bottles DP 0-1背包- 2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest
- codeforces 442 A. Alex and broken contest(水题)
- Codeforces 501A:Contest(水题)
- Codeforces 2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror)
- codeforces contest 358
- 【Codeforces】2015-2016 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2015) E 线段树+离散化
- Codeforces 2015-2016 ACM-ICPC, NEERC, Southern Subregional Contest B题 (排序贪心)
- Codeforces 2016 ACM Amman Collegiate Programming Contest A. Coins(动态规划/01背包变形)
- codeforces——contest 864 problemE
- codeforces April Fools Day Contest 2014 A. The Great Game
- CodeForces 377B-Preparing for the Contest(二分+贪心)
- codeforces contest 339
- codeforces contest 864 problemD
- CodeForces-2015 HIAST Collegiate Programming Contest-Gym-100952A-Who is the winner?
- codeforces contest 785 a题
- CodeForces 349B--Color the Fence(贪心)