POI2018
[BZOJ5099][POI2018]Pionek(极角排序+two pointers)
几个不会严谨证明的结论:
1.将所有向量按极角排序,则答案集合一定是连续的一段。
当答案方向确定时,则一个向量会被选入答案集合当且仅当向量在答案方向上的投影一定都是正的
所以,两个选中向量中间隔着一个向量,则必然可以将后面所有选中向量均前移一位并使答案不劣。
2.答案集合中不存在两个向量的极角差超过$\pi$。
显然需要保证的是,答案集合中任意两个向量投影不为负值,否则一定可以通过删去其中一个使答案更优。
3.当选择的向量集合区间左端点增加时,右端点单调不减。
感性理解,答案向量的极角会在选择的向量区间中某两个相邻向量极角之间。当区间左端点增加时,答案向量的极角必然增加,故右端点不会减少。
于是,将所有向量极角排序后,对所有扫过的极角极差不超过$\pi$的向量区间更新答案即可。
#include<cmath>
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=;
const double pi=acos(-.);
int n;
ll ans;
struct P{
int x,y; double s;
bool operator <(const P &a)const{ return s<a.s; }
P operator +(const P &a)const{ return (P){x+a.x,y+a.y}; }
P operator -(const P &a)const{ return (P){x-a.x,y-a.y}; }
ll len(){ return 1ll*x*x+1ll*y*y; }
}a[N]; int main(){
freopen("bzoj5099.in","r",stdin);
freopen("bzoj5099.out","w",stdout);
scanf("%d",&n);
rep(i,,n) scanf("%d%d",&a[i].x,&a[i].y),a[i].s=atan2(a[i].x,a[i].y);
sort(a+,a+n+); P cur=(P){,}; int x=;
rep(i,,n) a[i+n]=a[i],a[i+n].s+=*pi;
rep(i,,n){
while (x<n* && a[x+].s-a[i].s<=pi) cur=cur+a[++x],ans=max(ans,cur.len());
cur=cur-a[i]; ans=max(ans,cur.len());
}
printf("%lld\n",ans);
return ;
}
[BZOJ5100][POI2018]Plan metra(构造)
若1与n直接相连,则所有点到1与n的距离差的绝对值是相同的,根据距离选择与1还是n直接相连即可。
若不直接相连,则其余所有点到1与n的距离和的最小值就是1到n的距离。
找到所有在1到n的路径上的点,按与1的距离排序,然后相邻的两两连边。其余点算出应该挂在链上哪个点下面,注意判断各种不合法即可。
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=;
int n,a[N],b[N],id[N];
struct P{ int x,i; }d[N];
bool operator <(const P &a,const P &b){ return a.x<b.x; } int main(){
freopen("bzoj5100.in","r",stdin);
freopen("bzoj5100.out","w",stdout);
scanf("%d",&n);
rep(i,,n-) scanf("%d",&a[i]);
rep(i,,n-) scanf("%d",&b[i]);
if (n==){ printf("TAK\n1 2 1\n"); return ; }
int len=abs(a[]-b[]);
rep(i,,n-) if (abs(a[i]-b[i])!=len){ len=; break; }
if (len){
puts("TAK"); printf("1 %d %d\n",n,len);
rep(i,,n-)
if (a[i]>b[i]) printf("%d %d %d\n",i,n,b[i]);
else printf("%d %d %d\n",i,,a[i]);
return ;
}
len=; int tot=;
rep(i,,n-) len=min(len,a[i]+b[i]);
rep(i,,n) if (a[i]+b[i]==len) d[++tot]=(P){a[i],i};
sort(d+,d+tot+); d[]=(P){,}; d[++tot]=(P){len,n};
rep(i,,tot) if (d[i].x==d[i-].x){ puts("NIE"); return ; }
rep(i,,tot) id[d[i].x]=d[i].i;
rep(i,,n-) if (a[i]+b[i]>len && (((a[i]+b[i]-len)&) || !id[a[i]-(a[i]+b[i]-len)/])){ puts("NIE"); return ; }
puts("TAK");
rep(i,,tot) printf("%d %d %d\n",d[i-].i,d[i].i,d[i].x-d[i-].x);
rep(i,,n-) if (a[i]+b[i]>len) printf("%d %d %d\n",id[a[i]-(a[i]+b[i]-len)/],i,(a[i]+b[i]-len)/);
return ;
}
[BZOJ5101][POI2018]Powódź(并查集)
类似于Kruskal重构树上DP。
相邻点之间连一条权为墙高的边,将边从小到大排序,每次合并一条边连接的两个连通块。
h[i]表示连通块i中最高的墙,g[i]表示所有水位都不超过h[i]的情况下的方案数。最后答案就是g[1]+H-h[1]。
当某处水位高于h[i]时,水就会往四周流淌,所以合并边权为w的边连接的两个连通块时,h=w,g=(g1+w-h1)*(g2+w-h2)。
意思就是,新的方案数,等于两个连通块在水位均不超过w时的方案数之积。一个连通块水位不超过w的方案数,等于水位不超过h1的方案数,加所有区域水位相等且都大于h1的方案数,即g1+w-h1。
#include<cstdio>
#include<algorithm>
#define F(A,B) ((A-1)*m+B)
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=,mod=;
int n,m,H,x,tot,f[N],g[N],h[N];
struct E{ int u,v,w; }e[N<<];
bool operator <(const E &a,const E &b){ return a.w<b.w; }
int get(int x){ return (f[x]==x) ? x : f[x]=get(f[x]); } int main(){
freopen("bzoj5101.in","r",stdin);
freopen("bzoj5101.out","w",stdout);
scanf("%d%d%d",&n,&m,&H);
rep(i,,n) rep(j,,m-) scanf("%d",&x),e[++tot]=(E){F(i,j),F(i,j+),x};
rep(i,,n-) rep(j,,m) scanf("%d",&x),e[++tot]=(E){F(i,j),F(i+,j),x};
sort(e+,e+tot+);
rep(i,,n*m) f[i]=i,g[i]=,h[i]=;
rep(i,,tot){
int x=get(e[i].u),y=get(e[i].v);
if (x==y) continue;
g[y]=1ll*(g[x]+e[i].w-h[x])*(g[y]+e[i].w-h[y])%mod;
h[y]=e[i].w; f[x]=y;
}
printf("%d\n",(g[get()]+H-h[get()])%mod);
return ;
}
[BZOJ5102][POI2018]Prawnicy(堆)
区间排序后堆维护前k大,据说其它数据结构都被卡常了。
#include<queue>
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
typedef long long ll;
using namespace std; const int N=;
int n,m,ans,u,v;
struct P{ int l,r,id; }a[N];
bool operator <(const P &a,const P &b){ return a.r<b.r; }
priority_queue<int>Q; int main(){
freopen("bzoj5102.in","r",stdin);
freopen("bzoj5102.out","w",stdout);
scanf("%d%d",&n,&m);
rep(i,,n) scanf("%d%d",&a[i].l,&a[i].r),a[i].id=i;
sort(a+,a+n+);
for (int i=n; i; i--){
Q.push(a[i].l);
if (n-i+>=m){
int x=Q.top(); Q.pop();
if (a[i].r-x>ans) u=x,v=i,ans=a[i].r-x;
}
}
printf("%d\n",ans);
rep(i,v,n) if (a[i].l<=u) printf("%d ",a[i].id);
return ;
}
POI2018的更多相关文章
- bzoj5100 [POI2018]Plan metra 构造
5100: [POI2018]Plan metra Time Limit: 40 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 189 Sol ...
- [POI2018]Pionek
[POI2018]Pionek 题目大意: 在无限大的二维平面的原点放置着一个棋子.你有\(n(n\le2\times10^5)\)条可用的移动指令,每条指令可以用一个二维整数向量表示.请你选取若干条 ...
- bzoj千题计划249:bzoj5100: [POI2018]Plan metra
http://www.lydsy.com/JudgeOnline/problem.php?id=5100 1.找到d1[i]+dn[i] 最小的点,作为1到n链上的点 2.令链长为D,若abs(d1[ ...
- 【BZOJ5102】[POI2018]Prawnicy 堆
[BZOJ5102][POI2018]Prawnicy Description 定义一个区间(l,r)的长度为r-l,空区间的长度为0. 给定数轴上n个区间,请选择其中恰好k个区间,使得交集的长度最大 ...
- 【BZOJ5099】[POI2018]Pionek 几何+双指针
[BZOJ5099][POI2018]Pionek Description 在无限大的二维平面的原点(0,0)放置着一个棋子.你有n条可用的移动指令,每条指令可以用一个二维整数向量表示.每条指令最多只 ...
- 【BZOJ5100】[POI2018]Plan metra 构造
[BZOJ5100][POI2018]Plan metra Description 有一棵n个点的无根树,每条边有一个正整数权值,表示长度,定义两点距离为在树上的最短路径的长度. 已知2到n-1每个点 ...
- 【BZOJ5101】[POI2018]Powód 并查集
[BZOJ5101][POI2018]Powód Description 在地面上有一个水箱,它的俯视图被划分成了n行m列个方格,相邻两个方格之间有一堵厚度可以忽略不计的墙,水箱与外界之间有一堵高度无 ...
- bzoj 5099 [POI2018]Pionek 计算几何 极角排序
[POI2018]Pionek Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 269 Solved: 80[Submit][Status][Disc ...
- [bzoj5101][POI2018]Powódź_并查集
Powódź bzoj-5101 POI-2018 题目大意:在地面上有一个水箱,它的俯视图被划分成了$n$行$m$列个方格,相邻两个方格之间有一堵厚度可以忽略不计的墙,水箱与外界之间有一堵高度无穷大 ...
随机推荐
- 20155303 2016-2017-2 《Java程序设计》第八周学习总结
20155303 2016-2017-2 <Java程序设计>第八周学习总结 目录 学习内容总结(Linux命令) 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考 ...
- 002_curl及postman专题
一. 步骤 1: 下载cURL工具 使用您的Windows机器从cURL web站点下载最新版本的cURL: (1) 通常情况下,多数的Windows用户可以从官网下载页面http://curl.ha ...
- 十九、springboot使用@ControllerAdvice(二)之深入理解
前言: 接口类项目开发时,为了便于后期查找问题,一般会拦截器或过滤器中记录每个接口请求的参数与响应值记录, 请求参数很容易从request中获取,但controller的返回值无法从response中 ...
- java基础25 线程的常用方法、线程安全问题、死锁现象
一.线程的常用方法 1.Thread(String name):初始化线程的名字2. setName(String name):设置线程的名字3. getName():返回线程的名字4. sleep( ...
- 窗口启用/禁用功能函数EnableWindow的使用
在非MFC环境中如何使控件或者窗口禁用呢?起初是想通过发送消息来实现,但找来找去都木有找到控件禁用的消息(也是是博主木有找到的缘故),所以只能另辟蹊径,使用 EnableWindow这个函数, 该函数 ...
- maven pom.xml配置
<repositories> <repository> <id>central</id> <name>Maven Repository Sw ...
- POJ 1236 Network of Schools(tarjan求强连通分量+思维)
题目链接:http://poj.org/problem?id=1236 题目大意: 给你一个网络(有向图),有两个任务: ①求出至少同时需要几份副本可以使得整个网络都获得副本 ②至少添加多少信息表(有 ...
- Mysql建表语句
create table messages( id int unsigned primary key auto_increment, sender varchar(64) not null, gett ...
- 从一道简单的dp题中学到的...
今天想学点动态规划的知识,于是就看了杭电的课件,数塔问题啊,LCS啊都是比较经典的动规了,然后随便看了看就开始做课后练习题... HDOJ 1421 搬寝室 http://acm.hdu.edu.cn ...
- hdu 5120(求两个圆环相交的面积 2014北京现场赛 I题)
两个圆环的内外径相同 给出内外径 和 两个圆心 求两个圆环相交的面积 画下图可以知道 就是两个大圆交-2*小圆与大圆交+2小圆交 Sample Input22 30 00 02 30 05 0 Sam ...