Codeforces Round #219 (Div. 1)

来源:互联网 发布:mac os x 10.11破解版 编辑:程序博客网 时间:2024/05/01 19:42

这场一开始A题用set乱贪一发就交了,然后WA第六组。。。。然后二分乱搞过的。B题真的是想晕了,4秒的时限就是骗人的嘛。。。最后用1600*1600复杂度过的。。。思维不行,还需要好好练习。。。


A:

题意:

      把一个袋鼠装进另一个袋鼠。每个袋鼠只能装一个袋鼠且必须体积小于等于自己的一半。不能装 装了袋鼠的袋鼠。求最少剩       多少只袋鼠。


思路:二分有多少只袋鼠被装。


code:

#include <algorithm>#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <string>#include <math.h>#include <vector>#include <queue>#include <stack>#include <cmath>#include <list>#include <set>#include <map>using namespace std;#define N  500010#define ALL(x)     x.begin(),x.end()#define CLR(x,a)   memset(x,a,sizeof(x))typedef long long    ll;typedef pair<int,int> PI;const int INF    = 0x3fffffff;const int MOD    = 100000007;const double EPS = 1e-7;int n;int a[N];bool check(int x){for(int i=0;i<x;i++){if(2*a[i]>a[n-x+i]) return false;}return true;}int main(){scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d",&a[i]);sort(a,a+n);int l=0,r=n/2+1;while(l<r){int mid=(l+r)>>1;if(check(mid)) l=mid+1;else r=mid;}printf("%d\n",n-r+1);    return 0;}



B:


题意:求矩阵里有多少个子矩阵全包含零。


思路:dp[x0][y0][x1][y1] 表示矩阵{x0<=x<=x1,y0<=y<=y1}有多少个包含1的矩阵,tot[x0][y0][x1][y1]则表示有多少个子矩阵,对减下就是答案,递推的方法看代码,类似容斥。


比赛的时候没有去递推tot,一直以为是算一下组合数就是了,然后狂卡样例。。。。真是弱。。代码略翔,递推太长了。


code:

#include <algorithm>#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <string>#include <math.h>#include <vector>#include <queue>#include <stack>#include <cmath>#include <list>#include <set>#include <map>using namespace std;#define N  500010#define ALL(x)     x.begin(),x.end()#define CLR(x,a)   memset(x,a,sizeof(x))typedef long long    ll;typedef pair<int,int> PI;const int INF    = 0x3fffffff;const int MOD    = 100000007;const double EPS = 1e-7;int n,m;int sum[64][64][64][64];int tot[64][64][64][64];int main(){int x0,x1,y0,y1;scanf("%d%d",&n,&m);int Q;scanf("%d",&Q);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){scanf("%1d",&sum[i][j][i][j]);tot[i][j][i][j]=1;}for(int h=1;h<=n;h++){for(int w=1;w<=m;w++){if(h==1 && w==1) continue;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){int k=i+h-1,q=j+w-1;if(k>n || q>m) break;sum[i][j][k][q]+=sum[i+1][j][k][q]+sum[i][j+1][k][q]+sum[i][j][k-1][q]+sum[i][j][k][q-1];sum[i][j][k][q]-=sum[i+1][j+1][k][q]+sum[i+1][j][k-1][q]+sum[i+1][j][k][q-1]+sum[i][j+1][k-1][q]+sum[i][j+1][k][q-1]+sum[i][j][k-1][q-1];sum[i][j][k][q]+=sum[i+1][j+1][k-1][q]+sum[i+1][j+1][k][q-1]+sum[i+1][j][k-1][q-1]+sum[i][j+1][k-1][q-1];sum[i][j][k][q]-=sum[i+1][j+1][k-1][q-1];sum[i][j][k][q]+=(sum[i][j][k][q]>0);tot[i][j][k][q]+=tot[i+1][j][k][q]+tot[i][j+1][k][q]+tot[i][j][k-1][q]+tot[i][j][k][q-1];tot[i][j][k][q]-=tot[i+1][j+1][k][q]+tot[i+1][j][k-1][q]+tot[i+1][j][k][q-1]+tot[i][j+1][k-1][q]+tot[i][j+1][k][q-1]+tot[i][j][k-1][q-1];tot[i][j][k][q]+=tot[i+1][j+1][k-1][q]+tot[i+1][j+1][k][q-1]+tot[i+1][j][k-1][q-1]+tot[i][j+1][k-1][q-1];tot[i][j][k][q]-=tot[i+1][j+1][k-1][q-1];tot[i][j][k][q]++;}}}}while(Q--){scanf("%d%d%d%d",&x0,&y0,&x1,&y1);printf("%d\n",tot[x0][y0][x1][y1]-sum[x0][y0][x1][y1]);}    return 0;}


C:

题意:

        有n个看台排成一条直线。现在要放m次烟花。每次放烟花,你会获得b-|a-x|的收益,a表示烟花在哪个看台放,x是你所在的位置。每单位时间你最多能移动距离d,给出了每组烟花燃放的时间,求最大收益。


思路:

        dp[i][j] 表示燃放第i组烟花,此时人在第j个看台时候的最大收益。

        用dis表示从i-1到i最多能移动的距离,那么转移就是dp[i][j]=max{dp[i-1][k] | abs(j-k)<=dis }。用单调队列优化下,就能过了。


code:

#include <algorithm>#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <string>#include <math.h>#include <vector>#include <queue>#include <stack>#include <cmath>#include <list>#include <set>#include <map>using namespace std;#define N  200010#define ALL(x)     x.begin(),x.end()#define CLR(x,a)   memset(x,a,sizeof(x))typedef long long    ll;typedef pair<int,int> PI;const int INF    = 0x3fffffff;const int MOD    = 100000007;const double EPS = 1e-7;deque<int> que;ll dp[2][N];int main(){int n,m,d,pret=0,pre=1,now=0;int a,b,t;scanf("%d%d%d",&n,&m,&d);for(int i=0;i<m;i++){scanf("%d%d%d",&a,&b,&t);ll dis=1ll*d*(t-pret);pret=t;que.clear();for(int j=1;j<=n;j++){while(!que.empty() && dp[pre][j]>dp[pre][que.back()]) que.pop_back();que.push_back(j);while(dis<abs(que.front()-j)) que.pop_front();dp[now][j]=dp[pre][que.front()];}que.clear();for(int j=n;j>=1;j--){while(!que.empty() && dp[pre][j]>dp[pre][que.back()]) que.pop_back();que.push_back(j);while(dis<abs(que.front()-j)) que.pop_front();dp[now][j]=max(dp[now][j],dp[pre][que.front()]);}for(int j=1;j<=n;j++) dp[now][j]+=b-abs(j-a);swap(pre,now);}printf("%I64d\n",*max_element(dp[pre]+1,dp[pre]+n+1));    return 0;}



0 0
原创粉丝点击