icpc 2014 北京网络赛补完计划(3/8)(hdu5032-5040)
随便搜了一套题发现海星,就把有人过的题补了吧。
A-Always Cook Mushroom(hdu 5032)(待补)
B-Building(hdu 5033)
读入的时候有点问题所以一直wa,然后我现在才知道fabs和abs是不一样的,明明pas里是一样的。
只考虑每个观测点向左可以看到的角度,然后将对称地做一遍即可。实际上就是找到一个楼房使得其左边右边的楼房都不可以遮挡观测点的和此楼楼顶的连线,称为“关键楼房”好了,发现三个性质。
第一,如果一个楼房在另一个的左边,而且左边的楼房不比右边的楼房高,那么左边的楼房就不可能成为某一个观测点关键楼房(显然),这样对于一个观测点来说可能的关键楼房一定高度递减,用单调栈维护。
第二,如果三个楼房a,b,c从左至右依次排列且递减,那么如果a和b的楼顶形成的直线斜率绝对值比b和c楼顶形成的直线的绝对值大,那么b不可能成为某个观测点的关键楼房。证明略去,因为从右向左看楼顶与观测点形成的直线倾斜角度一定越来越小才有意义,手画一下就知道了。这样可以认为对于一个观测点来说可能的关键楼房一定是个上凸壳。
第三,如果一个观测点在另一个观测点的右边,且两个点之间没有楼房,那么右边观测点的关键楼房一定在左边观测点的观测楼房的左边,因为右边的观测点和楼顶形成的直线倾斜角度更小。
对于1和2,可以用一个单调栈来维护,然后只要不停地将不符合条件的栈顶弹出直到合法就行了(因为根据性质3被弹出的一定不可能成为之后的答案)。
1 #include <bits/stdc++.h> 2 #define ll long long 3 #define inf 0x6fffffff 4 #define N 100086 5 using namespace std; 6 int read(){ 7 int x=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 10 return x*f; 11 } 12 const double pi=atan(1.0)*4; 13 struct point{double x,y;int op,id;}p[N*3]; 14 bool cmp(point a,point b){return (a.x!=b.x)?a.x<b.x:a.op>b.op;} 15 int st[N*2]; 16 double ans[N]; 17 double calc(point a,point b) 18 { 19 return fabs((a.y-b.y)/(a.x-b.x)); 20 } 21 bool jud(point a,point b,point c) 22 { 23 point x={fabs(a.x-b.x),fabs(a.y-b.y)}; 24 point y={fabs(b.x-c.x),fabs(b.y-c.y)}; 25 return x.y*y.x-x.x*y.y>=0; 26 } 27 int main() 28 { 29 int T=read(); 30 for(int cas=1;cas<=T;cas++) 31 { 32 int n=read(); 33 for(int i=1;i<=n;i++)p[i].x=read(),p[i].y=read(),p[i].op=1; 34 int m=read(); 35 for(int i=n+1;i<=n+m;i++)p[i].x=read(),p[i].y=0,p[i].op=0,p[i].id=i-n; 36 n+=m; 37 for(int i=1;i<=m;i++)ans[i]=0; 38 sort(p+1,p+n+1,cmp); 39 int top=0; 40 for(int i=1;i<=n;i++) 41 if(p[i].op==1) 42 { 43 while(top&&p[st[top]].y<=p[i].y)top--; 44 while(top>1&&jud(p[st[top-1]],p[st[top]],p[i]))top--; 45 st[++top]=i; 46 } 47 else{ 48 if(top==0){ans[p[i].id]+=pi/2;continue;} 49 while(top>1&&jud(p[st[top-1]],p[st[top]],p[i]))top--; 50 ans[p[i].id]+=atan2(p[i].x-p[st[top]].x,p[st[top]].y); 51 } 52 top=0; 53 for(int i=n;i;i--) 54 if(p[i].op==1) 55 { 56 while(top&&p[st[top]].y<=p[i].y)top--; 57 while(top>1&&jud(p[st[top-1]],p[st[top]],p[i]))top--; 58 st[++top]=i; 59 } 60 else{ 61 if(top==0){ans[p[i].id]+=pi/2;continue;} 62 while(top>1&&jud(p[st[top-1]],p[st[top]],p[i]))top--; 63 ans[p[i].id]+=atan2(p[st[top]].x-p[i].x,p[st[top]].y); 64 } 65 printf("Case #%d: \n",cas); 66 for(int i=1;i<=m;i++)printf("%.10lf\n",ans[i]*180/pi); 67 } 68 //system("pause"); 69 return 0; 70 }
D-Delivery(hdu 5035)(待补)
E-Explosion(hdu 5036)(待补)
F-Frog(hdu 5037)
贪心。然后首先肯定是每个都尽量放成两个相隔L+1的石子然后中间插一个石子的情况。但是碰到他原来就给好的石子得特殊处理一下。就是一开始肯定是要把夹在两个相隔L+1的石子中的那个石子放在靠左的位置,此时离右边石子的距离res=l。然后如果两个初始给定的石子之间>l+1肯定只要考虑%(L+1)的那一部分,设这个值是mo。然后mo+res<L+1说明可以直接这么放下去,不过要改变中间石子的位置,即离右边石子的距离为mo+res,否则增加一部分,离右边石子距离为mo。好像说的有点迷……这一部分说起来好像比较麻烦,不过反正是签到题看看代码吧。
1 #include <bits/stdc++.h> 2 #define ll long long 3 #define inf 0x6fffffff 4 #define N 200086 5 using namespace std; 6 int read(){ 7 int x=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 10 return x*f; 11 } 12 int a[N]; 13 int main() 14 { 15 int T=read(); 16 for(int cas=1;cas<=T;cas++) 17 { 18 int n=read(),m=read(),l=read(); 19 for(int i=1;i<=n;i++)a[i]=read(); 20 a[0]=0,a[n+1]=m; 21 sort(a+1,a+n+1); 22 ll ans=0;int res=l; 23 for(int i=1;i<=n+1;i++) 24 { 25 int t=(a[i]-a[i-1])/(l+1),mo=(a[i]-a[i-1])%(l+1); 26 if(mo+res>=l+1)ans+=(ll)t*2+1,res=mo;else ans+=(ll)t*2,res+=mo; 27 } 28 printf("Case #%d: %lld\n",cas,ans); 29 } 30 system("pause"); 31 return 0; 32 }
G-Grade(hdu 5038)
签到题。
1 #include <bits/stdc++.h> 2 #define ll long long 3 #define inf 0x6fffffff 4 #define N 1000086 5 using namespace std; 6 int read(){ 7 int x=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 10 return x*f; 11 } 12 map<int,int> mp; 13 int w[N]; 14 int ans[N],ansnum; 15 int main() 16 { 17 int T=read(); 18 for(int cas=1;cas<=T;cas++) 19 { 20 int n=read();int appearnum=0;ansnum=0; 21 mp.clear(); 22 for(int i=1;i<=n;i++) 23 { 24 int x=read();w[i]=10000-(100-x)*(100-x); 25 mp[w[i]]++;appearnum+=(mp[w[i]]==1); 26 } 27 printf("Case #%d:\n",cas); 28 // for(int i=1;i<=n;i++) 29 int mx=0; 30 for(int i=1;i<=n;i++)mx=max(mx,mp[w[i]]); 31 for(int i=1;i<=n;i++) 32 if(mp[w[i]]==mx) 33 { 34 ans[++ansnum]=w[i];mp[w[i]]=0; 35 } 36 sort(ans+1,ans+ansnum+1); 37 if(ansnum==appearnum) 38 { 39 if(ansnum==1)printf("%d\n",ans[1]);else puts("Bad Mushroom"); 40 } 41 else{ 42 for(int i=1;i<ansnum;i++)printf("%d ",ans[i]); 43 printf("%d\n",ans[ansnum]); 44 } 45 } 46 system("pause"); 47 return 0; 48 }
H-Hilarity(hdu 5039)(待补)
I-Instrusive(hdu 5040)(待补)