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) 题意: 给 ...
随机推荐
- Spark RDD概念学习系列之RDD的容错机制(十七)
RDD的容错机制 RDD实现了基于Lineage的容错机制.RDD的转换关系,构成了compute chain,可以把这个compute chain认为是RDD之间演化的Lineage.在部分计算结果 ...
- 打开链接(C# / 默认浏览器)
System.Diagnostics.Process.Start("http://www.baidu.com/");
- Oracle- 用户管理
Oracle一个数据库里可以分配多个用户,用户创建自己的表,自己创建的表如果不想分配给其他用户使用,其他用户是看不到自己的创建的表的. 用户管理: 创建用户: create user chunxiao ...
- python学习(3)
Python学习(3)切片(Slice):根据索引范围取出字符串里面的内容,比如: l=range(100) l[:8] [0, 1, 2, 3, 4, 5, 6, 7] ...
- hdu2157之矩阵快速幂
How many ways?? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- RSA客户端js加密服务器C#解密(含源码)
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- iOS 基础知识
1获取系统语言设置 NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; NSArray *languages = ...
- js 数组详解(javascript array)
Array Array 对象用于在单个的变量中存储多个值. 构造函数: 1) new Array(); 2) new Array(size); 3) new Array(element0, ...
- 让Windows Server 2008 + IIS 7+ ASP.NET 支持10万并发请求(转)
转自:http://www.cnblogs.com/dudu/archive/2009/11/10/1600062.html 今天下午17点左右,博客园博客站点出现这样的错误信息: Error Sum ...
- [Whole Web] [AngularJS + Grunt] Using ng-html2js to Convert Templates into JavaScript
ng-html2js takes .html templates and converts them into strings stored in AngularJS's template cache ...