2015亚洲区域赛北京站A(二分)
2016-07-24 12:17
387 查看
思路:首先肯定是二分,然后求得一个大致结果,接下来有两种思路就是第一种是根据第一种结果尽可能再靠左的二分,第二种是直接从左到右暴力得到答案。
思路一:
#include <iostream> #include<string.h> #include<vector> #include<queue> #include<algorithm> #include<stdio.h> #include<math.h> using namespace std; const long long mod=1e9+7; typedef long long ll; struct data { int x,y,w,h; } p[10010]; bool cmp(data a,data b) { return a.x<b.x; } ll get(int mid,int n) { ll s=0; for(int i=0; i<n; i++) { if(p[i].x>mid) return s; if(p[i].x+p[i].w<=mid) { ll tt=(ll)p[i].w*(ll)p[i].h; s+=tt; } else { ll tt=(ll)(mid-p[i].x)*(ll)p[i].h; s+=tt; } } return s; } int main() { int t; scanf("%d",&t); while(t--) { int R; scanf("%d",&R); int n; scanf("%d",&n); ll sum=0; int bj=0; for(int i=0; i<n; i++) { int x,y,w,h; scanf("%d%d%d%d",&x,&y,&w,&h); if(x<R&&y>0&&x+w>0&&y-h<R) { if(x+w>R) w=R-x; if(y-h<0) h=y; p[bj].x=x,p[bj].y=y,p[bj].w=w,p[bj++].h=h; ll xx=(ll)w*(ll)h; sum+=xx; } } if(sum==0) { printf("%d\n",R); continue; } sort(p,p+bj,cmp); int l=0,r=R+1,mid=R/2; ll left=0,right=sum; while(l<r) { mid=(l+r)/2; left=get(mid,bj); right=sum-left; if(left>=right) r=mid; else l=mid+1; } ll x=get(r,bj); l=0,r=R+1; left=0; while(l<r) { mid=(l+r)/2; left=get(mid,bj); if(left>x) r=mid; else l=mid+1; } printf("%d\n",l-1); } return 0; }
思路二:
#include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #define ll long long using namespace std; struct point { ll l,t,w,h; } v[10050]; int n; bool vis[1000000]; int cmp(point a,point b) { return a.l<b.l; } ll get_area(int d) { ll sum=0; for(int i=0; i<n; i++) { if(v[i].l>d) continue; if(v[i].l+v[i].w<=d) sum+=v[i].h*v[i].w; else sum+=v[i].h*(d-v[i].l); } //cout<<"*****"<<sum<<endl; return sum; } int main() { int T; scanf("%d",&T); while(T--) { int R; memset(vis,0,sizeof(vis)); scanf("%d%d",&R,&n); ll sum=0; for(int i=0; i<n; i++) { scanf("%lld%lld%lld%lld",&v[i].l,&v[i].t,&v[i].w,&v[i].h); sum+=v[i].w*v[i].h; for(int j=v[i].l; j<v[i].l+v[i].w; j++) vis[j]=1; } sort(v,v+n,cmp); int l=0,r=R,mid=(l+r)/2; while(l<r) { mid=(l+r)/2; ll left=get_area(mid); ll right=sum-left; //cout<<left<<" "<<right<<endl; if(left==right) { //cout<<"FIND"<<endl; break; } else if(left<right) l=mid+1; else r=mid-1; } //cout<<"rrr"<<r<<" mid"<<mid<<endl; for(int i=l; i<=R; i++) { if(get_area(i)>=sum-get_area(i)) { //cout<<"find "<<i<<endl; for(int j=i; j<=R; j++) if(vis[j]==1||j==R) { printf("%d\n",j); break; } break; } } } return 0; }
相关文章推荐
- 简单的四则运算
- 数的奇偶性
- ACMer博客瀑布流分析
- ACM程序设计大赛题目分类
- 2015年acm国内排名
- 计算字符串最后一个单词长度
- ACM网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1002