zoukankan      html  css  js  c++  java
  • Codeforces 280

    280 A

    题意

    给你两个矩形,关于原点中心对称,其中一个矩形的边与坐标轴平行,另一个矩形能通过第一个矩形旋转得到,求两个矩形公共部分的面积。

    Examples

    Input
    1 1 45
    Output
    0.828427125
    Input
    6 4 30
    Output
    19.668384925

    求出所有点的坐标,然后用叉积求多边形的面积……

    Code

    #include<bits/stdc++.h>
    #define maxn 100003
    #define E 1e-8
    #define INF 1e16
    using namespace std;
    typedef double tp;
    int sgn(tp x){return x<-E?-1:x>E;}
    const double pi=acos(-1);
    struct point{
        tp x,y;
        point(){}
        point(tp _x,tp _y):x(_x),y(_y){}
        bool operator <(const point& p)const{return sgn(atan2(y,x)-atan2(p.y,p.x))<0;}
        bool operator ==(const point& p)const{return sgn(x-p.x)==0&&sgn(y-p.y)==0;}
        point operator +(const point& p)const{return point(x+p.x,y+p.y);}
        point operator -(const point& p)const{return point(x-p.x,y-p.y);}
        point operator *(tp k)const{return point(x*k,y*k);}
    };
    typedef point Vec;
    tp dot(const Vec& u,const Vec& v){return u.x*v.x+u.y*v.y;}
    tp cross(const Vec& u,const Vec& v){return u.x*v.y-v.x*u.y;}
    double dist(const point& p1,const point& p2){return sqrt(double(dot(p1-p2,p1-p2)));}
    
    bool seg_inter(const point& p1,const point& p2,const point& p3,const point& p4){
        return min(p1.x,p2.x)<=max(p3.x,p4.x)&&
        min(p3.x,p4.x)<=max(p1.x,p2.x)&&
        min(p1.y,p2.y)<=max(p3.y,p4.y)&&
        min(p3.y,p4.y)<=max(p1.y,p2.y)&&
        sgn(cross(p2-p1,p3-p1))*sgn(cross(p2-p1,p4-p1))<=0&&
        sgn(cross(p4-p3,p1-p3))*sgn(cross(p4-p3,p2-p3))<=0;
    }
    point inter(const point& P,const Vec& v,const point& Q,const Vec& w){
        if(!seg_inter(P,P+v,Q,Q+w))return point(INF,-INF);
        Vec u=P-Q;
        if(sgn(cross(v,w))==0){
            if(sgn(cross(Q-P,v))==0)return point(-INF,-INF); //chong he
            return point(INF,INF); //ping xing
        }
        tp t=cross(w,u)/cross(v,w);
        return P+v*t; //OK
    }
    
    point a[103],tmp;
    int n;
    point spin(const point& p,double t){
        double R=sqrt(p.x*p.x+p.y*p.y),B=atan2(p.y,p.x);
        return point(R*cos(t+B),R*sin(t+B));
    }
    int main(){
        double h,w,t;
        scanf("%lf%lf%lf",&w,&h,&t);
        t=t*pi/180;
        a[1]=point(w/2,h/2),a[2]=point(w/2,-h/2),a[3]=point(-w/2,-h/2),a[4]=point(-w/2,h/2);
        a[5]=spin(a[1],t),a[6]=spin(a[2],t),a[7]=spin(a[3],t),a[8]=spin(a[4],t);
        n=8;
        for(int i=1;i<=4;i++){
            for(int j=5;j<=8;j++){
                tmp=inter(a[i],(i==4?a[1]:a[i+1])-a[i],a[j],(j==8?a[5]:a[j+1])-a[j]);
                if(tmp.x!=INF&&tmp.x!=-INF)a[++n]=tmp;
            }
        }
        sort(a+1,a+n+1);
        double ans=cross(a[n],a[1]);
        for(int i=1;i<n;i++)ans+=cross(a[i],a[i+1]);
        printf("%.9lf
    ",2*w*h-abs(ans/2));
        return 0;
    }
    

    280 B

    题意

    一个序列的值定义为该序列最大值和次大值的异或。
    现在给你一个序列,求它的每一个子段的值的最大值。
    ((nle 10^5))

    Examples

    Input
    5
    5 2 1 4 3
    Output
    7
    Input
    5
    9 8 3 5 7
    Output
    15

    使用某种单调结构维护,可以手膜一下,然后发现完好无缺

    280 C

    题意

    给你一棵树,现在你要进行若干次操作,每次等概率选择一个节点并删除其子树和它本身,求期望多少次能将整棵树删光。 ((nle 10^5))

    Examples

    input
    2
    1 2
    output
    1.50000000000000000000
    input
    3
    1 2
    1 3
    output
    2.00000000000000000000

    答案为 (sum frac{1}{dep[i]})

    280 D

    题意

    求一个序列某段特定区间内的最大子段和,最多可以有不连续的 (k) 段,也可以是 (0) 段,答案为 (0) ,带单点修改。(n,Qle 10^5)

    Examples

    Input
    9
    9 -8 9 -1 -1 -1 9 -8 9
    3
    1 1 9 1
    1 1 9 2
    1 4 6 3
    Output
    17
    25
    0
    Input
    15
    -4 8 -3 -10 10 4 -7 -7 0 -6 3 8 -10 7 2
    15
    1 3 9 2
    1 6 12 1
    0 6 5
    0 10 -7
    1 4 9 1
    1 7 9 1
    0 10 -3
    1 4 10 2
    1 3 13 2
    1 4 11 2
    0 15 -9
    0 13 -9
    0 11 -10
    1 5 14 2
    1 6 12 1
    Output
    14
    11
    15
    0
    15
    26
    18
    23
    8

    首先用带反悔贪心或网络流瞎口胡得出一个结论:求一个区间 (k) 段最大子段和等价于进行 (k) 次以下操作:

    • 求出该区间的最大子段和;
    • 将答案加上最大子段和;
    • 将子段中的每个元素取相反数。

    这样我们就把该问题转换为了普通最大子段和问题。
    最后别忘了撤销操作。
    线段树维护区间普通最大子段和
    线段树需支持单点修改、区间取反、区间查询等操作。

    Code

    #include<bits/stdc++.h>
    #define maxn 100003
    using namespace std;
    struct node{
    	int lmx,lmxp,rmx,rmxp,mx,mxlp,mxrp,lmi,lmip,rmi,rmip,mi,milp,mirp,sum;
    	bool z;
    }t[maxn<<2];
    int n,Q,a[maxn],sykl[23],sykr[23];
    template<typename tp> tp max(tp x,tp y,tp z){return max(max(x,y),z);}
    template<typename tp> tp min(tp x,tp y,tp z){return min(min(x,y),z);}
    void new_node(node& t1,int pos,int k){
    	t1.lmx=t1.rmx=t1.mx=t1.lmi=t1.rmi=t1.mi=t1.sum=k;
    	t1.lmxp=t1.rmxp=t1.mxlp=t1.mxrp=t1.lmip=t1.rmip=t1.milp=t1.mirp=pos;
    }
    void pushup(node& t1,const node& t2,const node& t3){
    	t1.sum=t2.sum+t3.sum;
    	if(t2.lmx>t3.lmx+t2.sum)t1.lmx=t2.lmx,t1.lmxp=t2.lmxp;
    	else t1.lmx=t3.lmx+t2.sum,t1.lmxp=t3.lmxp;
    	if(t2.lmi<t3.lmi+t2.sum)t1.lmi=t2.lmi,t1.lmip=t2.lmip;
    	else t1.lmi=t3.lmi+t2.sum,t1.lmip=t3.lmip;
    	if(t3.rmx>t2.rmx+t3.sum)t1.rmx=t3.rmx,t1.rmxp=t3.rmxp;
    	else t1.rmx=t2.rmx+t3.sum,t1.rmxp=t2.rmxp;
    	if(t3.rmi<t2.rmi+t3.sum)t1.rmi=t3.rmi,t1.rmip=t3.rmip;
    	else t1.rmi=t2.rmi+t3.sum,t1.rmip=t2.rmip;
    	if(max(t2.mx,t3.mx,t2.rmx+t3.lmx)==t2.mx)t1.mx=t2.mx,t1.mxlp=t2.mxlp,t1.mxrp=t2.mxrp;
    	else if(max(t2.mx,t3.mx,t2.rmx+t3.lmx)==t3.mx)t1.mx=t3.mx,t1.mxlp=t3.mxlp,t1.mxrp=t3.mxrp;
    	else t1.mx=t2.rmx+t3.lmx,t1.mxlp=t2.rmxp,t1.mxrp=t3.lmxp;
    	if(min(t2.mi,t3.mi,t2.rmi+t3.lmi)==t2.mi)t1.mi=t2.mi,t1.milp=t2.milp,t1.mirp=t2.mirp;
    	else if(min(t2.mi,t3.mi,t2.rmi+t3.lmi)==t3.mi)t1.mi=t3.mi,t1.milp=t3.milp,t1.mirp=t3.mirp;
    	else t1.mi=t2.rmi+t3.lmi,t1.milp=t2.rmip,t1.mirp=t3.lmip;
    }
    void flip_node(node& t1){
    	t1.lmx=-t1.lmx,t1.rmx=-t1.rmx,t1.mx=-t1.mx,t1.lmi=-t1.lmi,t1.rmi=-t1.rmi,t1.mi=-t1.mi,t1.sum=-t1.sum;
    	swap(t1.lmx,t1.lmi),swap(t1.lmxp,t1.lmip),swap(t1.rmx,t1.rmi),swap(t1.rmxp,t1.rmip),swap(t1.mx,t1.mi),swap(t1.mxlp,t1.milp),swap(t1.mxrp,t1.mirp);
    }
    void pushdown(int p,int l,int r){
    	if(l==r)return;
    	if(t[p].z){
    		flip_node(t[p<<1]);
    		flip_node(t[p<<1|1]);
    		t[p<<1].z^=1;
    		t[p<<1|1].z^=1;
    		t[p].z=0;
    	}
    }
    void build(int p,int l,int r){
    	if(l==r){
    		new_node(t[p],l,a[l]);
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(p<<1,l,mid);
    	build(p<<1|1,mid+1,r);
    	pushup(t[p],t[p<<1],t[p<<1|1]);
    }
    void change(int p,int l,int r,int pos,int k){
    	pushdown(p,l,r);
    	if(l==r){
    		new_node(t[p],l,k);
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(pos<=mid)change(p<<1,l,mid,pos,k);
    	else change(p<<1|1,mid+1,r,pos,k);
    	pushup(t[p],t[p<<1],t[p<<1|1]);
    }
    void flip(int p,int l,int r,int seg_l,int seg_r){
    	pushdown(p,l,r);
    	if(seg_l<=l&&r<=seg_r){
    		flip_node(t[p]);
    		t[p].z^=1;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(seg_l<=mid)flip(p<<1,l,mid,seg_l,seg_r);
    	if(seg_r>mid)flip(p<<1|1,mid+1,r,seg_l,seg_r);
    	pushup(t[p],t[p<<1],t[p<<1|1]);
    }
    node query(int p,int l,int r,int seg_l,int seg_r){
    	pushdown(p,l,r);
    	if(seg_l<=l&&r<=seg_r){
    		return t[p];
    	}
    	int mid=(l+r)>>1;
    	node ret;
    	if(seg_l<=mid&&seg_r>mid)pushup(ret,query(p<<1,l,mid,seg_l,seg_r),query(p<<1|1,mid+1,r,seg_l,seg_r));
    	else if(seg_l<=mid)ret=query(p<<1,l,mid,seg_l,seg_r);
    	else if(seg_r>mid)ret=query(p<<1|1,mid+1,r,seg_l,seg_r);
    	return ret;
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",a+i);
    	build(1,1,n);
    	scanf("%d",&Q);
    	while(Q--){
    		int mo;
    		scanf("%d",&mo);
    		if(mo==0){
    			int pos,val;
    			scanf("%d%d",&pos,&val);
    			change(1,1,n,pos,val);
    		}
    		else{
    			int l,r,k,ans=0,i;
    			node syk;
    			scanf("%d%d%d",&l,&r,&k);
    			for(i=1;i<=k;i++){
    				syk=query(1,1,n,l,r);
    				if(syk.mx<0)break;
    				ans+=syk.mx;
    				sykl[i]=syk.mxlp;
    				sykr[i]=syk.mxrp;
    				flip(1,1,n,syk.mxlp,syk.mxrp);
    			}
    			printf("%d
    ",ans);
    			for(int j=1;j<i;j++){
    				flip(1,1,n,sykl[j],sykr[j]);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    html5 存储(删除)
    java 单例模式
    android知识点汇总
    java多线程 与 并发
    cuda GPU 编程之共享内存的使用
    vs 2015 + OPENGL 配置
    Ubuntu 14.04 安装 CUDA 问题及解决
    性能分析工具gprof介绍
    vim 换行方式 win 转Ubuntu vim 格式调整
    计算显卡对比
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/10557962.html
Copyright © 2011-2022 走看看