Urozero Autumn 2016. UKIEPC 2016
B. Build a Boat
首先求出每块船舱的面积$S$,然后进行$m$次二分,得到每个切割线的位置。
为了计算某个切割线形成的区域的面积,需要将多边形整理成上边界和下边界,分别二分出断点位置,中间部分用叉积前缀和$O(1)$回答。
时间复杂度$O(n+m\log^2n)$。
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=400010;
const double eps=1e-9;
int n,i,j,k,o,b[N],c[N],cb,cc,ans,lim,loc[N][2];ll all;
double each,s[N],mi,ma;
inline int sgn(double x){
if(x>eps)return 1;
if(x<-eps)return -1;
return 0;
}
struct P{
double x,y;
P(){}
P(double _x,double _y){x=_x,y=_y;}
P operator+(const P&b){return P(x+b.x,y+b.y);}
P operator-(const P&b){return P(x-b.x,y-b.y);}
P operator*(double b){return P(x*b,y*b);}
}a[N];
inline double cross(const P&a,const P&b){return a.x*b.y-a.y*b.x;}
inline P intersection(P a,P b,P p,P q){
double U=cross(p-a,q-p),D=cross(b-a,q-p);
return a+(b-a)*(U/D);
}
inline double cal(double x){
if(sgn(x-a[b[1]].x)<=0)return 0;//x>b[1]
if(sgn(x-a[b[cb]].x)>=0)return all;//x<b[cb]
int l=2,r=cb-1,mid,A=1,B=1;
while(l<=r){
mid=(l+r)>>1;
if(a[b[mid]].x<x)l=(A=mid)+1;else r=mid-1;
}
l=2,r=cc-1;
while(l<=r){
mid=(l+r)>>1;
if(a[c[mid]].x<x)l=(B=mid)+1;else r=mid-1;
}
l=b[A],r=c[B];
if(l>r)r+=n;
double ret=s[r-1]-s[l-1];
P X=intersection(a[b[A]],a[b[A+1]],P(x,-1),P(x,1)),
Y=intersection(a[c[B]],a[c[B+1]],P(x,-1),P(x,1));
ret+=cross(X,a[b[A]])+cross(a[c[B]],Y)+cross(Y,X);
return ret;
}
inline double solve(double goal){
double l=mi,r=ma,mid;
for(int i=0;i<60;i++){
mid=(l+r)/2;
if(fabs(cal(mid))<goal)l=mid;else r=mid;
}
return (l+r)/2;
}
int main(){
scanf("%d%d",&lim,&n);
for(i=1;i<=n;i++){
scanf("%d%d",&loc[i][0],&loc[i][1]);
a[i].x=loc[i][0],a[i].y=loc[i][1];
a[i+n]=a[i];
}
for(i=1;i<=n+n;i++)s[i]=s[i-1]+cross(a[i],a[i+1]);
for(i=1;i<n;i++)all+=loc[i][0]*loc[i+1][1]-loc[i][1]*loc[i+1][0];
all+=loc[n][0]*loc[1][1]-loc[n][1]*loc[1][0];
if(all<0)all*=-1;
ans=all/2/lim;
each=1.0*all/ans;
for(i=j=1;i<=n;i++)if(sgn(a[i].x-a[j].x)<0||sgn(a[i].x-a[j].x)==0&&sgn(a[i].y-a[j].y)>0)j=i;
for(i=o=1;i<=n;i++)if(sgn(a[i].x-a[o].x)>0||sgn(a[i].x-a[o].x)==0&&sgn(a[i].y-a[o].y)>0)o=i;
while(1){
b[++cb]=j;
if(j==o)break;
k=j-1;
if(k<1)k+=n;
j=k;
}
for(i=j=1;i<=n;i++)if(sgn(a[i].x-a[j].x)<0||sgn(a[i].x-a[j].x)==0&&sgn(a[i].y-a[j].y)<0)j=i;
for(i=o=1;i<=n;i++)if(sgn(a[i].x-a[o].x)>0||sgn(a[i].x-a[o].x)==0&&sgn(a[i].y-a[o].y)<0)o=i;
mi=1e9;ma=-mi;
for(i=1;i<=n;i++)mi=min(mi,a[i].x),ma=max(ma,a[i].x);
while(1){
c[++cc]=j;
if(j==o)break;
k=j+1;
if(k>n)k-=n;
j=k;
}
//for(i=1;i<=cb;i++)printf("(%.1f,%.1f) ",a[b[i]].x,a[b[i]].y);puts("");
//for(i=1;i<=cc;i++)printf("(%.1f,%.1f) ",a[c[i]].x,a[c[i]].y);puts("");
printf("%d\n",ans);
for(i=1;i<ans;i++)printf("%.9f\n",solve(each*i));
}
C. Compiler
只需要两个寄存器,设$f[i][j]$表示两个寄存器的值分别为$i,j$的最少步数,只有形如$a=a+kb(1\leq k\leq 2)$的操作有用,DP求出最优方案即可。
最坏情况下需要步数为$39$步,满足题目所给$40$步的限制。
时间复杂度$O(n^2)$。
#include<cstdio>
#include<string>
#include<vector>
#include<iostream>
using namespace std;
const int N=260,K=2;
int n=255,i,j,k,x,y,z,t,f[N][N],ans[N],mx;
vector<string>g[N][N],fin[N];
int main(){
for(i=1;i<=n;i++)ans[i]=N;
for(i=1;i<=n;i++)for(j=1;j<=n;j++)f[i][j]=N;
f[1][1]=3;
g[1][1].push_back("ST X");
g[1][1].push_back("ST Y");
for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(f[i][j]<N){
for(k=1;k<=K;k++){
z=f[i][j]+k*2+2;
if(i+i*k<=n){
x=i+i*k,y=j;
if(f[x][y]>z){
f[x][y]=z;
g[x][y]=g[i][j];
g[x][y].push_back("PH X");
for(t=1;t<=k;t++)g[x][y].push_back("PH X");
for(t=1;t<=k;t++)g[x][y].push_back("AD");
g[x][y].push_back("PL X");
}
}
if(i+j*k<=n){
x=i+j*k,y=j;
if(f[x][y]>z){
f[x][y]=z;
g[x][y]=g[i][j];
g[x][y].push_back("PH X");
for(t=1;t<=k;t++)g[x][y].push_back("PH Y");
for(t=1;t<=k;t++)g[x][y].push_back("AD");
g[x][y].push_back("PL X");
}
}
if(j+i*k<=n){
x=i,y=j+i*k;
if(f[x][y]>z){
f[x][y]=z;
g[x][y]=g[i][j];
g[x][y].push_back("PH Y");
for(t=1;t<=k;t++)g[x][y].push_back("PH X");
for(t=1;t<=k;t++)g[x][y].push_back("AD");
g[x][y].push_back("PL Y");
}
}
if(j+j*k<=n){
x=i,y=j+j*k;
if(f[x][y]>z){
f[x][y]=z;
g[x][y]=g[i][j];
g[x][y].push_back("PH Y");
for(t=1;t<=k;t++)g[x][y].push_back("PH Y");
for(t=1;t<=k;t++)g[x][y].push_back("AD");
g[x][y].push_back("PL Y");
}
}
}
if(ans[i]>f[i][j]){
ans[i]=f[i][j];
fin[i]=g[i][j];
fin[i].push_back("DI X");
}
if(ans[j]>f[i][j]){
ans[j]=f[i][j];
fin[j]=g[i][j];
fin[j].push_back("DI Y");
}
}
for(i=1;i<=n;i++)if(ans[i]>mx)mx=ans[i];
fin[0].push_back("ZE X");
fin[0].push_back("DI X");
//printf("%d",mx);
scanf("%d",&n);
for(i=0;i<fin[n].size();i++)cout<<fin[n][i]<<endl;
}
G. Gondolas
首先可以将时间都模$2T$,并将时间离散化,得到$O(n)$个时间,显然只在这些时间放置缆车最优。
枚举最早的缆车的时间,从前往后考虑每个时间是否设置缆车,则相邻两个缆车间的贡献是确定的,可以用前缀和$O(1)$求出。
设$f[i][j]$表示考虑前$i$个时间,时间$i$放置缆车,且一共放了$j$个缆车时,等待时间总和的最小值。
枚举上一个缆车的时间进行转移,可以斜率优化,自然也满足决策单调性,分治求解即可。
时间复杂度$O(n^2g\log n)$。
#include<cstdio>
#include<algorithm>
const int N=405,inf=~0U>>1;
int n,T,m,i,j,a[N],b[N],cnt,c[N],s[N],f[N][N],ans=inf;
inline void up(int&a,int b){a>b?(a=b):0;}
inline int cal(int l,int r){//[l..r] to r
return b[r]*(c[r]-c[l-1])-s[r]+s[l-1];
}
void solve(int l,int r,int dl,int dr,int p){
int m=(l+r)>>1,dm=dl,&dp=f[p][m];
for(int i=dl;i<=dr&&i<m;i++)if(f[p-1][i]<inf){
int t=f[p-1][i]+cal(i+1,m);
if(t<dp)dp=t,dm=i;
}
if(l<m)solve(l,m-1,dl,dm,p);
if(r>m)solve(m+1,r,dm,dr,p);
}
inline void solve(int st){
int i,j;
for(i=1;st+i-1<=cnt&&i<=m;i++){
for(j=1;j<=cnt;j++)f[i][j]=inf;
if(i==1)f[1][st]=cal(1,st);else solve(st+i-1,cnt,1,cnt,i);
for(j=st+i-1;j<=cnt;j++)if(f[i][j]<inf)up(ans,f[i][j]+(b[st]+T)*(c[cnt]-c[j])-s[cnt]+s[j]);
}
}
int main(){
scanf("%d%d%d",&n,&T,&m);T*=2;
for(i=1;i<=n;i++)scanf("%d",&a[i]),a[i]%=T;
std::sort(a+1,a+n+1);
for(i=1;i<=n;i++)if(i==1||a[i]>a[i-1])b[++cnt]=a[i];
for(i=1;i<=n;i++){
for(j=1;j<=cnt;j++)if(a[i]==b[j])break;
c[j]++,s[j]+=a[i];
}
for(i=1;i<=cnt;i++)c[i]+=c[i-1],s[i]+=s[i-1];
for(i=1;i<=cnt;i++)solve(i);
printf("%d",ans);
}
K. Compensation
对于正常以及延误两种情况分别预处理出$f[i][j]$表示于时刻$j$到达站点$i$,最早可以于什么时候到达站点$i+1$,那么可以在$O(n)$的时间内求出到达目的地的最早时间。
枚举每个起点为$1$的火车,计算第一步搭乘它且不延误时到达$n$的最早时间$A$以及与$S_i$时刻到达$1$号站点,在延误情况下到达$n$的最早时间$B$,若$A+1800\leq B$,则可以利用这辆火车延误进行索赔。
时间复杂度$O(nm)$。
#include<cstdio>
const int N=110,M=173000,inf=1000000000;
int n,m,i,e[M][4],ans=inf;
inline void up(int&a,int b){a>b?(a=b):0;}
struct P{
int f[N][M];
void init(){
for(int i=1;i<=n;i++)for(int j=0;j<M;j++)f[i][j]=inf;
}
inline void add(int x,int S,int T){
up(f[x][S],T);
}
void build(){
for(int i=1;i<=n;i++)for(int j=M-2;~j;j--)up(f[i][j],f[i][j+1]);
}
int cal(int x,int t){
for(int i=x;i<n;i++){
t=f[i][t];
if(t==inf)return inf;
}
return t;
}
}A,B;
int main(){
scanf("%d%d",&n,&m);
A.init();
B.init();
for(i=1;i<=m;i++){
scanf("%d%d%d%d",&e[i][0],&e[i][1],&e[i][2],&e[i][3]);
A.add(e[i][0],e[i][1],e[i][2]);
B.add(e[i][0],e[i][1]+e[i][3],e[i][2]+e[i][3]);
}
A.build();
B.build();
for(i=1;i<=m;i++)if(e[i][0]==1)if(A.cal(2,e[i][2])+1800<=B.cal(1,e[i][1]))up(ans,e[i][1]);
if(ans==inf)puts("impossible");else printf("%d",ans);
}
Urozero Autumn 2016. UKIEPC 2016的更多相关文章
- 【计算几何】【预处理】【枚举】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem K. Kiwi Trees
发现由于角的度数和边的长度有限制,那俩圆如果放得下的话,必然是塞在两个角里. 于是预处理n个圆心的位置(注意要判断那个圆会不会和其他的边界相交),然后n^2枚举俩角即可. #include<cs ...
- 【枚举】【SPFA】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem I. Iron and Coal
那个人派出的队伍的行走的路径一定前半程是重合的,后半程分叉开来. 于是预处理每个点离1号点的最短路,到最近的铁的最短路,到最近的煤的最短路.(三次BFS / SPFA)然后枚举分岔点,尝试更新答案即可 ...
- 【二分】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem C. Careful Ascent
二分Vx即可. #include<cstdio> #include<algorithm> using namespace std; #define EPS 0.00000000 ...
- 【强连通分量缩点】【DFS】【动态规划】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem B. British Menu
有向图,不经过重复点的最长链,强连通分量大小不超过5. 每个强连通分量内部暴力预处理任意两对点之间的最长路,外面DAG上dp. 不是很好写,但是预处理完了之后,可以重构每个强连通分量内部的结构,然后整 ...
- PHPStorm 2016.2 - 2016.3许可证服务器
最快,最安全的选择,以激活您的PHPStorm 2016.2 - 2016.3,这是足够的激活服务器,软件将自动激活.该过程将不断更新,如果不工作评价写入,如果有,以激活没有列出的服务器也可以说. 通 ...
- Windows Server 2016 + SCO 2016 安装及配置介绍
Windows Server 2016 + SCO 2016 安装及配置介绍 高文龙关注1人评论6332人阅读2017-02-26 23:23:02 Windows Server 2016 + SCO ...
- Urozero Autumn 2016. BAPC 2016
A. Airport Logistics 根据光路最快原理以及斯涅尔定律,可以得到从定点$P$进入某条直线的最佳入射角. 求出每个端点到每条线段的最佳点,建图求最短路即可. 时间复杂度$O(n^2\l ...
- Urozero Autumn 2016. NCPC 2016
A. Artwork 倒过来并查集维护即可. #include<cstdio> #include<algorithm> using namespace std; const i ...
- 深度学习的2016: NIPS 2016速览
With best wishes for a happy New Year! NIPS(Nerual Information Processing Systems)是人工智能.机器学习领域的顶级学术会 ...
随机推荐
- 论文阅读笔记二十八:You Only Look Once: Unified,Real-Time Object Detection(YOLO v1 CVPR2015)
论文源址:https://arxiv.org/abs/1506.02640 tensorflow代码:https://github.com/nilboy/tensorflow-yolo 摘要 该文提出 ...
- 集腋成裘-03-css基础-02
1.1 三种写法 内嵌式:样式只作用于当前文件,没有真正实现结构表现分离 外链式:作用范围是当前站点,真正实现了内容与表现分离 行内样式:仅限于当前标签,结构混在一起 1.2 标签分类 1.2.1 块 ...
- C/C++内存管理器
C标准库提供了malloc,free,calloc,realloc,C++标准库还提供了new, new[], delete, delete[].这些用来管理内存,看起来够用了,为啥还要自己写一个内存 ...
- js模板引擎art-Template(以前的artTemplate)
使用js.jquery动态生成html会非常麻烦.现在的模板引擎可以很简单的解决这个问题.比如腾讯出的art-Template 官网:http://aui.github.io/art-template ...
- 什么是redis的雪崩和穿透
缓存雪崩 如何应对缓存雪崩 首先要保证redis的高可用,可以使用redis cluster,开启redis持久化,redis之前要使用本地缓存,请求先走本地缓存,没找到再走redis 如果还是出现了 ...
- [warn] 7#7: *676 a client request body is buffered to a temporary file /var/cache/nginx/client_temp/0000000007
nginx 上传文件遇到的Bug. fastcgi_buffer_size 128k; fastcgi_buffers 8 128k; fastcgi_busy_buffers_size 128k; ...
- C++ ifstream ofstream
原文出自[比特网],转载请保留原文链接:http://soft.chinabyte.com/database/460/11433960.sh [导读] ofstream是从内存到硬盘,ifstream ...
- [转] createObjectURL方法 实现本地图片预览
ie6 可以直接显示本本地路径的图片 如: <img src="file://c:/3.jpg" /> ~~~网上都说ie7就不支持这种文件系统路径的url,但测试 ...
- uva 11367 (Dijkstra+DP)
题意:一辆汽车在一张无向图中开告诉你每个城市加油的费用.每次给q个查询(起点,终点,油箱容量)问你最小花费是多少. 思路:一道Dijkstra状态的题目.在这种最短路问题中一维的dis数组记录的信息往 ...
- 【AtCoder】ARC073
ARC 073 C - Sentou 直接线段覆盖即可 #include <bits/stdc++.h> #define fi first #define se second #defin ...