【PA2013】【BZOJ3839】Działka
来源:互联网 发布:apache安装包下载 编辑:程序博客网 时间:2024/05/01 08:14
Description
平面上有n个不重复的点。每次询问一个边平行坐标轴的矩形内(包含边界)的点组成的凸包的面积。
Input
第一行两个整数k,n(1<=k<=1000000,3<=n<=3000)。
接下来n行,每行两个整数x_i,y_i(0<=x_i,y_i<=k),表示点的坐标。
接下来一行一个整数m(1<=m<=1000000),表示询问数量。
接下来m行,每行四个整数a,b,c,d(0<=a< b<=k,0<=c< d<=k),表示询问的矩形范围为a<=x<=b,c<=y<=d。
Output
对于每个询问输出一行表示面积。保留小数点后一位。
Sample Input
9 7
1 1
1 3
3 3
3 1
6 5
6 6
7 3
3
0 4 0 4
2 7 0 7
3 7 3 6
Sample Output
4.0
10.0
6.0
HINT
Source
150s时限,卡评测好题
考虑把要求的凸包拆分成四部分:左上,左下,右上,右下
分别求每个点对按这四个方向构建凸包的面积(叉积)
对每个询问用线段树+扫描线把叉积累积起来求和然后除以二就是答案
询问限定的那四个范围没法直接处理,所以拆分询问+容斥
这题好厉害…%Claris…
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAXN 3010#define GET (ch>='0'&&ch<='9')#define lchild rt<<1,l,mid#define rchild rt<<1|1,mid+1,r#define ln rt<<1#define rn rt<<1|1#define SIZE 1000010#define LL long longusing namespace std;int k,n,m;LL ans;int sta[MAXN],top;inline void in(int &x){ char ch=getchar();x=0; while (!GET) ch=getchar(); while (GET) x=x*10+ch-'0',ch=getchar();}LL f[5][MAXN][MAXN];int que[5][SIZE];struct Point{ int x,y,id; inline friend Point operator -(Point a,Point b) {return (Point){a.x-b.x,a.y-b.y};} inline friend LL operator *(Point a,Point b) {return (LL)a.x*b.y-(LL)a.y*b.x;}}s[MAXN];inline LL cross(Point a,Point b,Point c) {Point A=b-a,B=c-b;return B*A;}inline bool cmp1(Point a,Point b) {return a.x==b.x?a.y<b.y:a.x<b.x;}inline bool cmp2(Point a,Point b) {return a.x==b.x?a.y>b.y:a.x<b.x;}inline bool cmp3(Point a,Point b) {return a.x<b.x;}inline bool cmp4(Point a,Point b) {return a.y<b.y;}int vis[MAXN],pos;struct seg {int l,r,x;}tree[SIZE<<2];inline void build(int rt=1,int l=0,int r=k){ tree[rt].x=0;tree[rt].l=l;tree[rt].r=r;int mid=(l+r)>>1; if (l==r) return; build(lchild);build(rchild);}inline void modify(int rt,int x,int delta){ int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1; tree[rt].x=delta; if (L==R) return; if (x<=mid) modify(ln,x,delta); else modify(rn,x,delta);}inline int merge(int x,int y) {return vis[x]>vis[y]?x:y;}inline int query(int rt,int l,int r){ int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1; if (l<=L&&r>=R) return tree[rt].x; if (r<=mid) return query(ln,l,r); if (l>mid) return query(rn,l,r); return merge(query(ln,l,mid),query(rn,mid+1,r));}struct Query{ int a,b,c,d; inline bool operator <(const Query& x)const {return a<x.a;}}q[SIZE],newq[SIZE];int main(){ in(k);in(n); for (int i=1;i<=n;i++) in(s[i].x),in(s[i].y),s[i].id=i; sort(s+1,s+n+1,cmp1); for (int i=2;i<=n;i++)//A { top=0;sta[top]=i;int l=s[sta[top]].id; for (int j=i-1;j;j--) if (s[j].y<=s[i].y) { while (top&&cross(s[j],s[sta[top]],s[sta[top-1]])<0) top--; f[1][l][s[j].id]=f[1][l][s[sta[top]].id]+s[sta[top]]*s[j];sta[++top]=j; } } sort(s+1,s+n+1,cmp2); for (int i=1;i<n;i++)//B { top=0;sta[top]=i;int l=s[sta[top]].id; for (int j=i+1;j<=n;j++) if (s[j].y<=s[i].y) { while (top&&cross(s[sta[top-1]],s[sta[top]],s[j])<0) top--; f[2][l][s[j].id]=f[2][l][s[sta[top]].id]+s[sta[top]]*s[j];sta[++top]=j; } } for (int i=2;i<=n;i++)//C { top=0;sta[top]=i;int l=s[sta[top]].id; for (int j=i-1;j;j--) if (s[j].y>=s[i].y) { while (top&&cross(s[j],s[sta[top]],s[sta[top-1]])>0) top--; f[3][l][s[j].id]=f[3][l][s[sta[top]].id]+s[sta[top]]*s[j];sta[++top]=j; } } sort(s+1,s+n+1,cmp1); for (int i=1;i<n;i++)//D { top=0;sta[top]=i;int l=s[sta[top]].id; for (int j=i+1;j<=n;j++) if (s[j].y>=s[i].y) { while (top&&cross(s[sta[top-1]],s[sta[top]],s[j])>0) top--; f[4][l][s[j].id]=f[4][l][s[sta[top]].id]+s[sta[top]]*s[j];sta[++top]=j; } } in(m); for (int i=1;i<=m;i++) in(q[i].a),in(q[i].b),in(q[i].c),in(q[i].d); for (int i=1;i<=m;i++) newq[i]=(Query){q[i].d,q[i].a,q[i].b,i};//考虑用容斥得到询问答案 sort(s+1,s+n+1,cmp4);sort(newq+1,newq+m+1);int i,j; for (build(1,0,k),i=j=1;i<=m;i++) { while (j<=n&&s[j].y<=newq[i].a) modify(1,s[j].x,s[j].id),vis[s[j++].id]=++pos; que[1][newq[i].d]=query(1,newq[i].b,newq[i].c); } for (int i=1;i<=m;i++) newq[i]=(Query){q[i].c,q[i].a,q[i].b,i}; sort(s+1,s+n+1,cmp4);sort(newq+1,newq+m+1); for (build(1,0,k),i=m,j=n;i;i--) { while (j&&s[j].y>=newq[i].a) modify(1,s[j].x,s[j].id),vis[s[j--].id]=++pos; que[3][newq[i].d]=query(1,newq[i].b,newq[i].c); } for (int i=1;i<=m;i++) newq[i]=(Query){q[i].b,q[i].c,q[i].d,i}; sort(s+1,s+n+1,cmp3);sort(newq+1,newq+m+1); for (build(1,0,k),i=j=1;i<=m;i++) { while (j<=n&&s[j].x<=newq[i].a) modify(1,s[j].y,s[j].id),vis[s[j++].id]=++pos; que[4][newq[i].d]=query(1,newq[i].b,newq[i].c); } for (int i=1;i<=m;i++) newq[i]=(Query){q[i].a,q[i].c,q[i].d,i}; sort(s+1,s+n+1,cmp3);sort(newq+1,newq+m+1); for (build(1,0,k),i=m,j=n;i;i--) { while (j&&s[j].x>=newq[i].a) modify(1,s[j].y,s[j].id),vis[s[j--].id]=++pos; que[2][newq[i].d]=query(1,newq[i].b,newq[i].c); } for (int i=1;i<=m;i++) { ans=f[1][que[1][i]][que[2][i]]-f[2][que[1][i]][que[4][i]]-f[3][que[3][i]][que[2][i]]+f[4][que[3][i]][que[4][i]]; printf("%lld.%d\n",ans>>1,ans&1ll?5:0); }}
1 0
- 【PA2013】【BZOJ3839】Działka
- BZOJ3839: [Pa2013]Działka
- 【PA2013】
- ka.py
- 【PA2013】【BZOJ3733】Iloczyn
- 【杂题】bzoj3735[Pa2013]Konduktorzy
- 【PA2013】【BZOJ3837】Filary
- [Pa2013]Karty 解题报告
- 【bzoj3733】[Pa2013]Iloczyn
- BZOJ3837: [Pa2013]Filary
- kA*与(kA)*的行列式计算
- 夏天的味道 ka
- ka代码问题
- [BZOJ3837][Pa2013][随机][乱搞]Filary
- senyum atau bibir Ka
- [暴搜剪枝] BZOJ 3733 [Pa2013]Iloczyn
- bzoj 3838: [Pa2013]Raper (线段树)
- About Ka-shing Li------one wonderful man.
- HDOJ 1002 高精度加法
- 我的Android进阶之旅------>Android关于HttpsURLConnection一个忽略Https证书是否正确的Https请求工具类
- 基础:逻辑和证明
- POJ1269 Intersecting Lines(计算几何)
- Learning Structured Embeddings of Knowledge Bases-笔记
- 【PA2013】【BZOJ3839】Działka
- Android setFocusable(true)和requestFocus()的区别
- ubuntu-vsftpd
- HDU 3911 Black And White
- sql 建立文件组示例
- http请求出现相同参数服务端怪现象
- 使用MapReduce实现关系代数的代码
- UILocalNotification本地通知01
- 如何关闭浏览器输入框自动补齐