$$ \newcommand{\seq}[2]{{#1}_{1},{#1}_{2},\cdots,{#1}_{#2}} \newcommand{\num}[1]{1,2,\cdots,#1} \newcommand{\stra}[2]{\begin{bmatrix}#1 \\ #2\end{bmatrix}} \newcommand{\strb}[2]{\begin{Bmatrix}#1 \\ #2\end{Bmatrix}} \newcommand{\dw}[1]{\underline{#1}} \newcommand{\up}[1]{\overline{#1}} $$

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\n",2*w*h-abs(ans/2));
    return 0;
}

280 B

题意

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

Examples

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

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

280 C

题意

给你一棵树,现在你要进行若干次操作,每次等概率选择一个节点并删除其子树和它本身,求期望多少次能将整棵树删光。 \((n\le 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,Q\le 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\n",ans);
			for(int j=1;j<i;j++){
				flip(1,1,n,sykl[j],sykr[j]);
			}
		}
	}
	return 0;
}
posted @ 2019-03-19 13:07  chc_1234567890  阅读(186)  评论(0编辑  收藏  举报