zoukankan      html  css  js  c++  java
  • BZOJ4418: [Shoi2013]扇形面积并

    BZOJ4418: [Shoi2013]扇形面积并

    Description

    给定N个同心的扇形,求有多少面积,被至少K个扇形所覆盖。

    Input

    第一行是三个整数n,m,k。n代表同心扇形的个数,m用来等分 [-π,π]的弧度。
    从第二行开始的n行,每行三个整数r,a1,a2。描述了一个圆心在原点的扇形,半径为r,圆心角是从弧度πa1/m到πa2/m,a1可能大于a2,逆时针扫过的区域为该扇形面积。

    Output

    输出一个整数ans,至少被K个扇形所覆盖的总面积等于π/2m×ans
    保证答案不超过2^63-1

    Sample Input

    【输入样例1】
    3 8 2
    1 -8 8
    3 -7 3
    5 -5 5
    【输入样例2】
    2 4 1
    4 4 2
    1 -4 4

    Sample Output

    【输出样例1】
    76
    【输出样例2】
    98

    HINT

    对于100%的数据,1≤n≤10^5,   1≤m≤10^6,1≤k≤5000,1≤ri≤10^5,-m≤a1,a2≤m


    题解Here!
    很容易想到把每个扇形转换成矩形,然后就变成了矩形覆盖。
    于是扇形的半径就是举行的宽。
    我们发现$a_1<a_2$就直接搞,那$a_1>a_2$呢?
    我们可以将$[a_1,a_2],a_1>a_2$拆成$[a_1,m]+[-m,a_2]$,这个问题就解决了。
    将每个矩形拆成两个操作:加入宽或删除宽。
    这玩意很显然用权值线段树就好。
    不会?静态区间第$k$大写过没?主席树写过没?
    然后用扫描线把所有询问差分一下。
    每进行一次操作,用线段树找当前的第$k$大(也就是找当前用来算答案的的半径是多少)。
    然后就是一波乱搞算出答案了。
    附上奇丑无比的代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define DATA(x) a[x].data
    #define LSIDE(x) a[x].l
    #define RSIDE(x) a[x].r
    #define MAXN 100010
    using namespace std;
    int n,m,q,d=0;
    struct Segment_Tree{
    	int data,l,r;
    }a[MAXN<<2];
    struct Fan{
    	int r,x,c;
    }b[MAXN<<2];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline bool cmp(const Fan &p,const Fan &q){
    	return p.x<q.x;
    }
    inline void add(int r,int x,int y){
    	d++;
    	b[d].r=r;b[d].x=x;b[d].c=1;
    	d++;
    	b[d].r=r;b[d].x=y;b[d].c=-1;
    }
    inline void pushup(int rt){
    	DATA(rt)=DATA(LSON)+DATA(RSON);
    }
    inline void buildtree(int l,int r,int rt){
    	LSIDE(rt)=l;RSIDE(rt)=r;
    	if(l==r){
    		DATA(rt)=0;
    		return;
    	}
    	int mid=l+r>>1;
    	buildtree(l,mid,LSON);
    	buildtree(mid+1,r,RSON);
    	pushup(rt);
    }
    void update(int l,int r,int c,int rt){
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
    		DATA(rt)+=c;
    		return;
    	}
    	int mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)update(l,r,c,LSON);
    	if(mid<r)update(l,r,c,RSON);
    	pushup(rt);
    }
    int query(int k,int rt){
    	if(k<=0)return 0;
    	if(DATA(rt)<k)return 0;
    	if(LSIDE(rt)==RSIDE(rt))return LSIDE(rt);
    	if(k<=DATA(LSON))return query(k,LSON);
    	else return query(k-DATA(LSON),RSON);
    }
    void work(){
    	long long ans=0;
    	for(int i=1;i<=d;i++){
    		if(i>1){
    			int k=query(DATA(1)-q+1,1);
    			if(k)ans+=1LL*k*k*(b[i].x-b[i-1].x);
    		}
    		update(b[i].r,b[i].r,b[i].c,1);
    	}
    	printf("%lld
    ",ans);
    }
    void init(){
    	int r,x,y,maxn=0;
    	n=read();m=read();q=read();
    	for(int i=1;i<=n;i++){
    		r=read();x=read();y=read();
    		x+=m;y+=m;
    		maxn=max(maxn,r);
    		if(x<=y)add(r,x,y);
    		else{
    			add(r,0,y);
    			add(r,x,(m<<1));
    		}
    	}
    	sort(b+1,b+d+1,cmp);
    	buildtree(1,maxn,1);
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    
  • 相关阅读:
    URAL 1207 极角排序
    URAL 1348 求垂足
    POJ 3608 旋转卡壳
    POJ 2954 Pick定理
    POJ 2007 叉积排序
    UVA 10002 凸多边形重心
    [转]bad interpreter:No such file or directory的原因
    [转]实现Python HTTP服务方法大总结
    urllib2.HTTPError: HTTP Error 403: Forbidden 错误
    C++二分查找代码
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9525157.html
Copyright © 2011-2022 走看看