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;
}