2016百度之星复赛 1003 拍照 优先队列

2016"百度之星" - 复赛(Astar Round3)

Ended

2016-05-29 14:00:00 - 2016-05-29 17:00:00 Current Time: 00:46:02

Solved Pro.ID Title Ratio(Accepted / Submitted) Language
  1001 D++游戏 13.79% (16/116) 中文
  1002 K个联通块 17% (136/800) 中文
1003 拍照 22.49% (434/1930) 中文
  1004 XOR 游戏 22.14% (114/515) 中文
  1005 带可选字符的多字符串匹配 0.52% (1/194) 中文
  1006 矩阵方程的解 6.61% (8/121) 中文

1003 拍照

题意:给出n艘船的(x,y,z,d),x和y代表船左端点和右端点的横坐标,z为船的纵坐标,都为整数,d代表每艘船的方向,1为向右、-1为向左。所有船运动速度相同。如下图,主角可以在z=0的直线上任意一点拍照,照相机视角90度,只能垂直向上拍,问一张照片最多能拍到多少艘完整的船。

题解:

因为相同方向的船是相对静止的,我们可以先考虑静止的情况,分别对两种方向的船进行考虑,然后再综合各自的结果来得出总的答案。

考虑静止情况:

要是枚举每艘船的左端点与左射界重合,检查有多少船在视野中,肯定能得到最优解,但复杂度O(n^2),要思考能否低复杂度枚举船并计算视野中船数。

我们可以把船按照x+z排序(x+z即以该船左端点与左射界重合时,拍照点的横坐标),然后从大到小扫,讲扫到的点的y-z加入大端优先队列中。每当优先队列中最大的数大于当前的x+z,就把它弹出,因为它在视野右边了。这样,当前的优先队列大小就是看到的船数。O(n)得出以各个船为左射界时的船数。

对两个方向做以上处理,得到往左的若干个照相点,往右的若干个照相点,然后考虑两个方向的某个照相点能否重合。

也用优先队列,先把两方向照相点各自按横坐标排序,把往左照相点从小到大扫一遍,扫的时候把 往右照相点集中的 横坐标小于当前照相点的照相点 的船数加入优先队列,更新答案 ans = max(ans , 优先队列中最大的 + 当前点船数),扫一遍就无敌了,也是O(n)。

总的复杂度就是排序的nlog(n)

代码:

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 /**Header!**/ //{
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<cstring>
  7 #include<algorithm>
  8 #include<cmath>
  9 #include<map>
 10 #include<set>
 11 #include<stack>
 12 #include<queue>
 13 using namespace std;
 14
 15 #define MZ(array) memset(array, 0, sizeof(array))
 16 #define MF1(array) memset(array, -1, sizeof(array))
 17 #define MINF(array) memset(array, 0x3f, sizeof(array))
 18 #define REP(i,n) for(i=0;i<(n);i++)
 19 #define FOR(i,x,n) for(i=(x);i<=(n);i++)
 20 #define ROF(i,x,y) for(i=(x);i>=(y);i--)
 21 #define RD(x) scanf("%d",&x)
 22 #define RD2(x,y) scanf("%d%d",&x,&y)
 23 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
 24 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
 25 #define WN(x) printf("%d\n",x);
 26 #define RE  freopen("D.in","r",stdin)
 27 #define WE  freopen("huzhi.txt","w",stdout)
 28 #define MP make_pair
 29 #define PB push_back
 30 #define PF push_front
 31 #define PPF pop_front
 32 #define PPB pop_back
 33 #define lowbit(x) ((x)&(-x))
 34 #define cindiao ios_base::sync_with_stdio(0)
 35 #define fcout(x,y) cout << fixed << setprecision(x) << (y) << endl
 36 typedef long long LL;
 37 typedef unsigned long long ULL;
 38 typedef pair<int,int> PII;
 39 template<class T>inline void OA(const T &a,const int &st,const int &ed) {
 40     if(ed>=st)cout<<a[st];
 41     int i;
 42     FOR(i,st+1,ed)cout<<‘ ‘<<a[i];
 43     puts("");
 44 }
 45 template <class T> inline T quickPow(T p,T e,const T &M){
 46     LL ret = 1;
 47     for(; e > 0; e >>= 1){
 48         if(e & 1) ret = (ret * p) % M;
 49         p = (p * p) % M;
 50     } return (T)ret;
 51 }
 52 template <class T> inline T gcd(const T &a,const T &b){return (b==0) ? a : gcd(b,a%b);}
 53 template <class T> inline T niyuan(const T &a, const T &M){return quickPow(a,M-2,M);}
 54 template <class T> inline T exgcd(const T &a,const T &b,T &x,T &y) {
 55     if (!b) {x=1,y=0;return a;}
 56     T ret=exgcd(b,a%b,x,y), t;
 57     t=x,x=y,y=t-a/b*y;
 58     return ret;
 59 }
 60 template <class T> inline T niyuanex(const T &a, const T &M){
 61     T x,y;
 62     exgcd(a,M,x,y);
 63     return (x+M)%M;
 64 }
 65 inline LL calC(const int &n,int m,const LL &MOD){
 66     m=(n-m>m)?m:(n-m);
 67     LL up=1,down=1;
 68     int i;
 69     for(i=1;i<=m;i++){
 70         down*=i;
 71         down%=MOD;
 72         up*=(n-i+1);
 73         up%=MOD;
 74     }
 75     return (up*niyuanex(down, MOD))%MOD;
 76 }
 77 inline LL Lucas(const int &n,const int &m, const int &MOD) {
 78     if(m==0)return 1;
 79     return (1LL * Lucas(n/MOD, m/MOD, MOD)*calC(n%MOD, m%MOD, MOD))%MOD;
 80 }
 81 const int gx[4] = {-1,0,1,0};
 82 const int gy[4] = {0,1,0,-1};
 83 const double PI=acos(-1.0);
 84 //}
 85 const double EPS=1e-10;
 86 inline int sgn(double &x) {
 87     if(fabs(x) < EPS)return 0;
 88     if(x < 0)return -1;
 89     else return 1;
 90 }
 91 const int INF=0x3f3f3f3f;
 92 const int NINF=0x80000001;
 93 const int MAXN=11111;
 94 const int MAXM=33;
 95 const int MOD = 1000000007;
 96
 97 struct Node{
 98     int x,y,z;
 99     Node(){}
100     Node(int _x,int _y,int _z){
101         x=_x;
102         y=_y;
103         z=_z;
104     }
105     inline bool operator<(const Node &q)const{
106         return x+z < q.x +q.z;
107     }
108 }a[2][MAXN];
109 int an[2];
110
111 int n;
112
113 inline int farm(){
114     int i,j;
115     map<int,int> ans[2];
116     int ans2[2];
117     map<int,int>::iterator it,it2;
118     REP(i,2){
119         sort(a[i],a[i]+an[i]);
120         priority_queue<int> pq;
121         while(!pq.empty())pq.pop();
122         ans[i].clear();
123         ans2[i]=0;
124 //        printf("%d!%d!\n",i,an[i]);
125         ROF(j,an[i]-1,0){
126             Node now = a[i][j];
127             int mid = now.x + now.z;
128             pq.push(now.y-now.z);
129             while(!pq.empty() && pq.top() > mid)
130                 pq.pop();
131 //            printf("%d,%d,%d\n",now.x,now.y,now.z);
132             int sz = pq.size();
133             ans[i][mid] = max(ans[i][mid], sz);
134             ans2[i] = max(ans2[i], sz);
135         }
136     }
137 //    printf("%d,%d\n",ans2[0],ans2[1]);
138     int re = max(ans2[0], ans2[1]);
139     it2 = ans[1].begin();
140     set<int> st;
141     st.clear();
142     for(it = ans[0].begin(); it!=ans[0].end(); it++){
143         while(it2!=ans[1].end() && it2->first <= it->first){
144             st.insert(it2->second);
145             it2++;
146         }
147         if(st.size()!=0){
148             set<int>::iterator it3 = st.end();
149             it3--;
150             re = max(re , it->second + *it3);
151         }
152     }
153     return re;
154 }
155
156 int main(){
157     int T,t=1;
158     int i;
159     int x,y,z,d;
160     RD(T);
161     while(T--){
162         RD(n);
163         MZ(an);
164         an[0]=an[1]=0;
165         REP(i,n){
166             RD4(x,y,z,d);
167             if(d==-1){
168                 a[0][an[0]]=Node(x,y,z);
169                 an[0]++;
170             }else{
171                 a[1][an[1]]=Node(x,y,z);
172                 an[1]++;
173             }
174         }
175 //        printf("%d,%d!\n",an[0],an[1]);
176         printf("Case #%d:\n",t++);
177         WN(farm());
178     }
179     return 0;
180 }

听说1002是状压DP,1004是Trie树乱搞。

时间: 2024-08-06 02:19:31

2016百度之星复赛 1003 拍照 优先队列的相关文章

2016&quot;百度之星&quot; - 复赛(Astar Round3) 1003 拍照

拍照 思路:先静态,离线树状数组,分别统计每个点向左向右能看到的船的数量.再枚举整个区间求最大值. 应为人和船都是动态的,假设船往左走,处理每个点看到向左最大船的数量,满足动态条件.就是向左的船一开始在最右边,向右的船一开始在最左边,则两船肯定相向运动到某个地方最佳. 1 //#pragma comment(linker, "/STACK:167772160")//手动扩栈~~~~hdu 用c++交 2 #include <cstdio> 3 #include <cs

2016 百度之星 复赛 - 拍照

小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行.小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中. 小明位于河的边上,并且可以在河边的任意位置进行拍照,照相机的视野恰好为90度角,只能以垂直于河边的方向进行拍照.河上的船只全都可看作是平行于河边的一条线段,跟河边的距离各不相同,有的正在向左移动,有的正在向右移动,但移动速度恰好都是一样的.小明可以等待恰当的时间让尽量多的船只都走进照相机的视野里,你不需要考虑船只之间会互相遮挡视野的情况

hdu5714 拍照[2016百度之星复赛C题]

由于船移动的速度都一样,那么对于往一个方向的船相对距离其实是不变的,我们可以把往一个方向移动的船都视作静止,并求出在哪些观测位置可以看到,很明显对于船[x,y,z],当x+z>=y-z的时候,可以在[y-z,x+z]这些位置观测到它,这些位置的观测数全都+1,然后考虑不同方向,假设初始在x位置观测往右的船,在y位置观测到往左的船,只要x<=y,则经过一段时间的移动,必然存在一个位置可以同时观测到x位置和y位置能观测到的船.复杂度O(nlogn). 代码 1 #include<cstdio

hdu5713 K个联通块[2016百度之星复赛B题]

dp 代码 1 #include<cstdio> 2 const int N = 30000; 3 const int P = 1000000009; 4 int n,m,k,cnt[N]; 5 long long f[N],g[N],o[N],dp[N][15]; 6 int e[15][15],i,j,l,a,b; 7 int check(int x,int y) 8 { 9 int i; 10 for (i=0;i<n;i++) 11 if ((1<<i)==x) br

hdu5715 XOR 游戏 [2016百度之星复赛D题]

 比赛的时候没仔细想,赛后一想这题其实挺简单的,先求出序列的异或前缀和,然后将异或前缀和建出一颗trie树,然后我们可以二分答案,把问题变成判定性问题,判定是否存在一种方案,使得所有的分组的异或和都大于等于这个二分的答案,然后就可以dp了,用f[i][j]表示到j为止能不能分成i组,f[i][j]=f[i-1][j-k]|f[i-1][j-k+1]...|f[i-1][j-1],这个东西用trie树维护一下就可以了.单组数据复杂度O(nmlogn^2) 代码 1 #include<cstdio>

2016百度之星 补题记

2016"百度之星" - 复赛(Astar Round3) 拍照 思路:先把所有的线段投影到x轴,然后将所有线段的起末坐标存进数组,排序后从坐标最小开始枚举.如果遇到起点标志,就加一:结束点标志减一.如此即可求出同一时刻,遇到当前线段结束点时,有多少线段包含在内 /************************************************************** Problem:hdu 5417 User: youmi Language: C++ Result

HDU 5698 瞬间移动 (2016&quot;百度之星&quot; - 初赛(Astar Round2B) 1003)

传送门 瞬间移动 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 140 Accepted Submission(s): 66 Problem Description 有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝色格子),求到第n行第m列的格子有几种方案

2016百度之星总结帖

2016百度之星总结帖 测试赛 选的2015资格赛的部分题目,第二题字符串处理,第三题map计数 1001 大搬家 f f (x) = x 两次置换后回到原位 dp a->b && b->a,考虑n个数 如果它独自成对,那么就有s[n-1]: 如果它与前面某个成对,首先可以有n-1个可取,然后每个都有s[n-2]: 故s[n] = s[n-1] + (n-1)s[n-2]; 1004 放盘子 今天他向来访者们提出一个恶俗的游戏.他和来访者们轮流往一个正多边形内放盘子.最后放盘子

2016&quot;百度之星&quot; - 初赛(Astar Round2A)解题报告

此文章可以使用目录功能哟↑(点击上方[+]) 有点智商捉急,第一题卡了好久,看来不服老,不服笨是不行的了...以下是本人目前的题解,有什么疑问欢迎提出 链接→2016"百度之星" - 初赛(Astar Round2A)  Problem 1001 All X Accept: 0    Submit: 0 Time Limit: 2000/1000 mSec(Java/Others)    Memory Limit : 65536 KB  Problem Description F(x,