2016.08.06计算几何总结测试day1
T1 bzoj1132[POI2008]TRO
还是太弱了。。。。测试时看到这题直接懵逼,极角排序什么的根本想不起来,只会n^3暴力怎么破。。。。。。不过竟然有84。。。。。QAQ
正解是n^2logn的,首先为了避免算重,以点的x坐标为第一关键字和y坐标为第二关键字排好序,然后O(n)枚举当前点计算以当前点为三角形的一个顶点的三角形面积之和。
显然不能n^2枚举,于是想到nlogn极角排序,以当前点为原点建一个平面直角坐标系,加一个前缀和将计算优化到O(n),于是就是n^2logn的了
至于怎么前缀和优化,因为一个点j,向量ij与前面所有的向量的叉积之和就是向量ij的贡献。
然后稍微手推一下就可以得出ans+=sumx*a[j].y-sumy*a[j].x就可以O(n)了。。。。。
精度问题什么的考虑一下就好了。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 10000 int n,tot;
long long sumx,sumy,ans; struct point{
int x,y;
double slope;
}a[maxn],b[maxn]; bool cmp(point a,point b){
return a.x<b.x||(a.x==b.x&&a.y<b.y);
} bool cmp_slope(point a,point b){
return a.slope<b.slope;
} int main(){
scanf("%d",&n);
for (int i=;i<=n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a+,a+n+,cmp);
for (int i=;i<=n;i++){
tot=,sumx=,sumy=;
for (int j=i+;j<=n;j++) b[++tot].slope=atan2(a[j].y-a[i].y,a[j].x-a[i].x),b[tot].x=a[j].x-a[i].x,b[tot].y=a[j].y-a[i].y;
sort(b+,b+tot+,cmp_slope);
for (int j=;j<=tot;j++){
ans+=sumx*b[j].y-sumy*b[j].x;
sumx+=b[j].x,sumy+=b[j].y;
}
}
printf("%lld.%d",ans>>,(ans&)?:);
return ;
}
T1
T2 bzoj1038[ZJOI2008]瞭望塔
测试时看到这题认为最可写,于是码了1h+杂技写法,以为用一个单调栈维护斜率什么的搞一搞就行了,然而并没有看到瞭望塔能建在[x1,xn]的任意位置。。。。。
然后发现这就是一道半平面交的题,对每个拐点求出它左右最远能望到哪个点,然后连两条直线,对于所有在这条直线上方的点,它都可以看到,由于光路可逆原理,直线上方任意的点也能看到它。
然后这就是许多个半平面,求半平面交就好了。。。
然而测试时傻叉的以为半平面内y最小的点一定最优。。。。。于是狗带。。。。竟然还有80。。。
正解是半平面交的下凸壳可以看成分段一次函数,折线下方村落的折线也可以看成分段一次函数,然后求两段一次函数之间的最小距离,必定会在端点上而不会是直线上的某一点的距离。
因为折线可以分解为一段一段的直线,对于每一段直线,它所对应的直线斜率无论是比它大还是小,最短距离都取决于端点,平行也是一样,YY一下就会觉得它很正确。。。很显然。。。
于是上半平面交。。。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 330
const double inf=1e10; int n,tot,sum,head,tail;
double ans; struct point{
double x,y;
}p[*maxn],a[*maxn],pa[*maxn]; struct line{
point from,to;
double slope;
}l[*maxn],q[*maxn]; point operator -(point a,point b){return(point){a.x-b.x,a.y-b.y};}
double operator *(point a,point b){return a.x*b.y-a.y*b.x;}
bool operator <(line a,line b){
return (a.slope==b.slope)?((a.to-a.from)*(b.to-a.from)<):a.slope<b.slope;
}
bool operator ==(line a,line b){
return a.slope==b.slope;
} point getpoint(line a,line b){
double t1=(a.to-a.from)*(b.to-a.from),t2=(b.from-a.from)*(a.to-a.from);
double t=t1/(t1+t2);
return (point){b.to.x+t*(b.from.x-b.to.x),b.to.y+t*(b.from.y-b.to.y)};
} bool check(line a,line b,line c){
point d=getpoint(a,b);
return ((c.to-c.from)*(d-c.from)<);
} double find1(double x){
for (int i=;i<=n;i++)
if (x>=a[i].x && x<a[i+].x){
line tmp1,tmp2;
tmp1.from=(point){x,},tmp1.to=(point){x,max(a[i].y,a[i+].y)};
tmp2.from=(point){a[i].x,a[i].y},tmp2.to=(point){a[i+].x,a[i+].y};
point ttt=getpoint(tmp1,tmp2);
return ttt.y;
}
return a[n].y;
} double find2(double x){
for (int i=head;i<=tail;i++)
if (x>=q[i].from.x && x<=q[i].to.x){
line tmp;
tmp.from=(point){x,},tmp.to=(point){x,max(q[i].from.y,q[i].to.y)};
point ttt=getpoint(tmp,q[i]);
return ttt.y;
}
} void solve(){
head=,tail=;
q[]=l[],q[]=l[];
for (int i=;i<=sum;i++){
while (head<tail && check(q[tail-],q[tail],l[i])) tail--;
while (head<tail && check(q[head+],q[head],l[i])) head++;
q[++tail]=l[i];
}
while (head<tail && check(q[tail-],q[tail],q[head])) tail--;
while (head<tail && check(q[head+],q[head],q[tail])) head++;
q[tail+]=q[head];
for (int i=head;i<=tail;i++){
point t=getpoint(q[i],q[i+]);
q[i].to=q[i+].from=t;
ans=min(ans,fabs(t.y-find1(t.x)));
}
for (int i=;i<=n;i++)
ans=min(ans,fabs(a[i].y-find2(a[i].x)));
printf("%.3f",ans);
} int main(){
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
scanf("%d",&n);
ans=inf,inf;
for (int i=;i<=n;i++)
scanf("%lf",&a[i].x);
for (int i=;i<=n;i++)
scanf("%lf",&a[i].y);
l[++tot].from=(point){-inf,-inf},l[tot].to=(point){inf,-inf};
l[++tot].from=(point){inf,inf},l[tot].to=(point){-inf,inf};
for (int i=;i<=n;i++){
int k=;
for (int j=i+;j<=n;j++){
if (a[j].y<=a[i].y) continue;
if (!k) k=j;
else if ((a[k]-a[i])*(a[j]-a[i])>) k=j;
}
if (k) l[++tot].from=a[i],l[tot].to=a[k];
}
for (int i=n;i;i--){
int k=;
for (int j=i-;j;j--){
if (a[j].y<=a[i].y) continue;
if (!k) k=j;
else if ((a[k]-a[i])*(a[j]-a[i])<) k=j;
}
if (k) l[++tot].to=a[i],l[tot].from=a[k];
}
l[++tot].from=(point){a[].x,inf},l[tot].to=(point){a[].x,-inf};
l[++tot].from=(point){a[n].x,-inf},l[tot].to=(point){a[n].x,inf};
for (int i=;i<=tot;i++) l[i].slope=atan2(l[i].to.y-l[i].from.y,l[i].to.x-l[i].from.x);
sort(l+,l+tot+);
sum=unique(l+,l+tot+)-l;
sum--;
solve();
return ;
}
T2
T3 bzoj4677 network
zy加题果然神速。。。。。
测试时由于T2打太久了,而且样例都还没过。。。。于是情急之下5分钟打了一个T3 n^2暴力,发现过了样例开心得不得了,然而手抽多打一个0,MLE。。。。。。。QAQ
这是一个类似杨辉三角的转移过程,可以发现,对于f[x][y],能够转移的p[]的区间是[y-x+1,y],含义是第只有第(y-x+1)种运输线到第y种运输线可能在转移过程中出现。
发现这是一个区间的问题,于是就立马能想到线段树。。。然后开开心心地找到区间[y-x+1,y]的最小值,然后转移,开开心心submit,然后WA。。。。。
因为对于最小值转移正确性无法保证,因为你只能保证p[k]最小,不能保证sigma(p[k+1],p[y])+p[k]最小。
于是考虑最优解的形式,因为一旦起点确定,你要往下走多少次,往右走多少次也确定了,因为对于每一条运输线都要往下走,你可以选择的是竖直向下,也可以选择斜向下,而往斜要走多少次已经确定了,为什么不在这条路径上(注意,是这条路径上)走最多次最小的k呢?
那么对于任取一起点k的最优解,一定就是如下图所示的情况
那么既然要从某k走到权值最优的k,那么为什么不直接以权值最优的k为起点呢?那么新的情况就如下图
这样一来,无论如何对于这条路径也无法优化了,那么这一定就是最优解的形式。
因为如果要每次走到最优的k再不断往下走,不如选最优的k为起点,然而这也仅仅只是最优解的形式,并不能直接选取它作为最优解,而最优解的形式已经确定下来了,这就为我们解题带来了很大方便。
考虑对于每一个区间内的k,都令它直接往下走,走到不能走为止,再往左。
因为如果这个k它本身的权值是不够优的,还让它一直往下走,显然这不是以该k为起点的路径的最优解,但实际上选它作为起点的路径本就是没有意义的,因为完全可以以该路径上最优的点作为起点,因此即使该方案不够优,却不会影响到答案,因为已经确定了解的形式,且该决策本就是没有意义的。
但如果这个k足够优,那么显然如果让它一直往下走,它的决策不会比其他的方案差,所以对于能影响到答案的决策,它是最优的。
如果还是不能理解,换句话说,决策序列其实是非降的,因为对于k1<k2,还有p[k1]>p[k2],则k1一定没有k2优,而在决策序列元素l[i],l[i+1],对于它们在原来的p[]序列中中间夹的所有数p[j]都一定有p[j]>l[i] && p[j]>l[i+1](如果它能成为一个决策,那么就一定会有这样的一个性质),也就是说,如果用决策序列将原来的p[]序列分成若干块,块内的元素都是单调不升的。
而且每个块最后一个元素都要优于块内其余所有的元素。若对于每个元素的最优解显然是把它的路径先伸展到该块最后一个元素,但它们是一定没有该块最后一个元素优的,所以一路下来又有何妨。同样,每块最后一个元素无论是最优路径还是最优解形式的路径都是一样的,这也是能够更新答案的路径,它们的解都是最优的。
那么对于一个k,最优解形式就是k出现(x-y+k)次,其余[k+1,y]只出现一次。
也就是求一个min{(x-y+k)*p[k]+sigma(p[i]|(k+1<=i<=y))}
令sum[i]表示sigma(p[i]),那么就有相当于min{(x-y)*p[k]+k*p[k]-sum[k]}+sum[y]
令k=(x-y),x=p[k],y=k*p[k],即求kx+y。令kx+y=b,转化为直线令截距最小,即是用线段树维护一个上凸壳。
时间复杂度O(nlog^2n)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 100010
#define inf 1e15
int top,n,m;
int p[maxn];
long long ans;
long long sum[maxn];
struct point{
int x;
long long y;
}val[maxn],stack[maxn*];
point operator -(point a,point b){return(point){a.x-b.x,a.y-b.y};}
long long operator *(point a,point b){return a.x*b.y-a.y*b.x;}
struct segment_tree{
int begin,end,size;
}tree[maxn<<];
void push(point x,int tmp){
while (top>tmp && (stack[top]-stack[top-])*(x-stack[top])<=) top--;
stack[++top]=x;
}
void merge(int p){
int lson=p<<,rson=p<<|,lbeg=tree[lson].begin,rbeg=tree[rson].begin,tmp=top+;
tree[p].begin=top+;
while (lbeg<=tree[lson].end && rbeg<=tree[rson].end){
point x;
if (stack[lbeg].x<stack[rbeg].x||(stack[lbeg].x==stack[rbeg].x && stack[lbeg].y<stack[rbeg].y)) x=stack[lbeg++];
else x=stack[rbeg++];
push(x,tmp);
}
while (lbeg<=tree[lson].end) push(stack[lbeg++],tmp);
while (rbeg<=tree[rson].end) push(stack[rbeg++],tmp);
tree[p].end=top;
}
void build(int p,int l,int r){
if (l==r){
tree[p].begin=tree[p].end=++top;
stack[top]=val[l];
return;
}
int mid=(l+r)>>;
build(p<<,l,mid);
build(p<<|,mid+,r);
merge(p);
}
long long calc(int p,int x,int y){return (long long)stack[p].x*(x-y)+stack[p].y+sum[y];}
void solve(int p,int x,int y){
int l=tree[p].begin,r=tree[p].end;
while (r-l>=){
int mid=l+(r-l)/,midmid=r-(r-l)/;
if (calc(mid,x,y)<calc(midmid,x,y)) r=midmid;
else l=mid;
}
for (int i=l;i<=r;i++) ans=min(ans,calc(i,x,y));
}
void query(int p,int l,int r,int x,int y,int tmpx,int tmpy){
if (x<=l && r<=y){
solve(p,tmpx,tmpy);
return;
}
int mid=(l+r)>>;
if (x<=mid) query(p<<,l,mid,x,y,tmpx,tmpy);
if (y>mid) query(p<<|,mid+,r,x,y,tmpx,tmpy);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) scanf("%d",&p[i]),sum[i]=sum[i-]+p[i],val[i]=(point){p[i],(long long)i*p[i]-sum[i]};
build(,,n);
for (int i=,x,y;i<=m;i++){
scanf("%d%d",&x,&y);
x^=ans,y^=ans;
ans=inf;
query(,,n,y-x+,y,x,y);
printf("%lld\n",ans);
}
return ;
}
T3
2016.08.06计算几何总结测试day1的更多相关文章
- 2016.08.07计算几何总结测试day2
T1 bzoj: [Usaco2010 OPen]Triangle Counting 数三角形 看到这个题n那么大, 于是想到极角排序搞一搞,然而排完序后立马懵逼,完全不知道接下来应该怎么写.... ...
- 最新版Theos.2016.08的安装方法
http://bbs.pediy.com/showthread.php?t=212425 标题: [翻译]手把手安装最新版Theos.2016.08作者: roysue时间: 2016-08-26,1 ...
- http://tedhacker.top/2016/08/05/Spring%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/
http://tedhacker.top/2016/08/05/Spring%E7%BA%BF%E7%A8%8B%E6%B1%A0%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%9 ...
- 新手C#构造函数、继承、组合的学习2018.08.06/07
构造函数,是一种特殊的方法.主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同 ...
- 新手C#属性set,get的学习(部分转)2018.08.06
public class person { public string name; } public class person { public string Name { set; get; } } ...
- 新手C#面向对象的学习2018.08.06
class Person//声明一个Person类 { //类中的声明与Main中不同,类中声明的是字段而不是函数. public string gender; public string name= ...
- 2021.08.06 P4392 Sound静音问题(ST表)
2021.08.06 P4392 Sound静音问题(ST表) [P4392 BOI2007]Sound 静音问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 序列a,求 ...
- 2021.08.06 P2441 角色属性树(树形结构)
2021.08.06 P2441 角色属性树(树形结构) P2441 角色属性树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 求离x最近的祖先y且(x,y)>1. ...
- 2021.08.06 P3478 STA-Station(树形结构)
2021.08.06 P3478 STA-Station(树形结构) [P3478 POI2008]STA-Station - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 给 ...
随机推荐
- POJ1838
poj 1838 这道题主要是对并查集的考察,在这道题的解题过程中主要用到的算法就是并查集中的最基本的makeSet,findSet,unionSet 即前篇文章中所提到的: makeSet(Elem ...
- PC-hosts 的使用 [可使电脑无法正常上网]
1.文件中记录了IP与服务器. 2.此文件修改后,电脑将无法正常上网,请别乱动. 文件地址: C:\WINDOWS\system32\drivers\etc [hosts]
- 问题-提示“adodataset.command”
问题现象:提示“adodataset.command” 问题原因:原因不明,希望高人指点. 问题处理:如果报adodataset.command ,如果忽略将删除控件的错误时,你应该可以看一看是不是在 ...
- Struts文件上传机制
1首先建立文件上传jsp页面如下 <form action="" method="post" enctype="multipart/form-d ...
- [置顶] 项目进阶 之 持续构建环境搭建(二)Nexus私服器
上一篇博文项目进阶 之 持续构建环境搭建(一)架构中,我们大致讲解了一下本系列所搭建环境的基本框架,这次开始我们进入真正的环境搭建实战.重点不在于搭建的环境是否成功和完善,而是在搭建过程中充分认识到每 ...
- 微软的.NET示例代码放在Github上了
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:微软的.NET示例代码放在Github上了.
- 关于.net的一些基础知识(二)
索引器是什么?有什么作用?索引器允许类的实例以访问数组的形式来访问对象里面的属性.如我们经常可以看到类似于dr[“name”]=”test”,或者说以config[“connectString”]来获 ...
- CSS3超酷移动手机滑动隐藏側边栏菜单特效
这是一组共4种效果很炫酷的CSS3移动手机滑动隐藏側边栏菜单特效. 这四种效果各自是:默认的点击滑动側边栏菜单效果.带3D transforms的滑动側边栏效果.文字缩放和淡入淡出效果的滑动側边栏以及 ...
- yum 命令提示语法错误
1. 问题信息 SyntaxError: invalid syntax 2. 问题原因 升级python版本导致 3. 解决方法 vi /usr/bin/yum 将#!/usr/bin/python ...
- 使用HttpURLConnection实现在android客户端和服务器之间传递对象
一般情况下,客户端和服务端的数据交互都是使用json和XML,相比于XML,json更加轻量级,并且省流量,但是,无论我们用json还是用xml,都需要我们先将数据封装成json字符串或者是一个xml ...