从天而降很多个多边形,现在有n(1<=n<=25000)个询问,询问区间[l,r]之间多边形的面积
第一行表示数据组数T
每一组数据第一行包含一个整数n,表示操作的数量
R P 表示有一个多边形出现了,这个多边形有p个点,接下来的一行有2*p个数,以逆时针方向给出多边形的形状
Q A B 查询区间[A,B]的面积
Sample Input
1
7
Q 1 100
R 4
10 10 11 10 13 11 12 11
Q 10 11
Q 1 100
R 3
100 20 120 20 110 30
Q 1 100
Q 12 120
Sample Output
0.000
0.250
1.000
1.000
100.250
第一行表示数据组数T
每一组数据第一行包含一个整数n,表示操作的数量
R P 表示有一个多边形出现了,这个多边形有p个点,接下来的一行有2*p个数,以逆时针方向给出多边形的形状
Q A B 查询区间[A,B]的面积
Sample Input
1
7
Q 1 100
R 4
10 10 11 10 13 11 12 11
Q 10 11
Q 1 100
R 3
100 20 120 20 110 30
Q 1 100
Q 12 120
Sample Output
0.000
0.250
1.000
1.000
100.250
Hint:无小数据
把原来的梯形变成了多边形,但是,其实仔细观察后可以发现任意一个多边形都可以剖成多个梯形,一个重要的技巧就是,因为数据保证是逆时针读入,而只要我们花一个图就可以轻松发现,当从左往右枚举顶点的时候,把两个顶点之间与过最低点的水平线组成的一个直角梯形作为负面积,相反从右往左便利时候的构成的直角梯形作为正面积,然后用正面积减掉负面积就可以得到多边形的面积,好了,这就转化成为最开始的冰雪奇缘的问题了。这也是一个很重要的技巧吧。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ls u<<1,l,mid
#define rs u<<1|1,mid,r
#define maxn 25020
#include<map>
using namespace std;
void init(){
freopen("B.in","r",stdin);
freopen("B.out","w",stdout);
}
int n,cur[maxn*10],tot,cnt;
struct node{
int l,r;
double len,ladd,radd,s;
}nod[maxn * 4];
struct question{
int a[6],b[6],flag,n,id,Min;
bool operator <(const question& b)const{return id<b.id;}
}que[maxn*9];
int ttot;
struct new_question{
double h1,h2;
int x1,x2,id;
bool operator<(const new_question& b)const{return id<b.id;}
new_question():id(0){}
}ne[maxn*9];
void change(int i){//把 多边形变成梯形
for(int j=2;j<=que[i].n;j++){
if(que[i].a[j]>que[i].a[j-1]){
ne[++tot].h1=-(que[i].b[j-1]-que[i].Min),ne[tot].h2=-(que[i].b[j]-que[i].Min);
ne[tot].x1=que[i].a[j-1];ne[tot].x2=que[i].a[j];
}
else {
ne[++tot].h1=que[i].b[j]-que[i].Min,ne[tot].h2=que[i].b[j-1]-que[i].Min;
ne[tot].x1=que[i].a[j];ne[tot].x2=que[i].a[j-1];
}
}
ne[++tot].h1=que[i].b[1]-que[i].Min,ne[tot].h2=que[i].b[que[i].n]-que[i].Min;
ne[tot].x1=que[i].a[1];ne[tot].x2=que[i].a[que[i].n];
}
bool cmp(int a,int b){return a<b;}
void front(){
sort(cur+1,cur+1+cnt,cmp);//离散化横坐标
cnt=unique(cur+1,cur+1+cnt)-cur-1;
//把多边形变成直角梯形
for(int i=1;i<=n;i++){
if(que[i].flag==1){
change(i);
}
else {
ne[++tot].id=24;
ne[tot].x1=que[i].a[1],ne[tot].x2=que[i].b[1];
}
}
}
void build(int u,int l,int r){
nod[u].ladd=nod[u].radd=nod[u].s=0; nod[u].l=l,nod[u].r=r; nod[u].len=cur[r]-cur[l];
if(l==r-1){
return ;
}
int mid=l+r>>1;
build(ls);
build(rs);
}
void push_up(int u){
int ll=u<<1,rr=u<<1|1;
nod[u].s=nod[ll].s+nod[rr].s;
}
double Q(int x,double y,int a,double b,int mid){
return (double)y+(b-y)*1.0*(cur[mid]-cur[x])*1.0/(cur[a]-cur[x])*1.0;
}
void push_down(int u){
if(nod[u].ladd==0&&nod[u].radd==0)return ;
double x=Q(nod[u].l,nod[u].ladd,nod[u].r,nod[u].radd,nod[u].r+nod[u].l>>1);
int ll=u<<1,rr=u<<1|1;
nod[ll].ladd+=nod[u].ladd;
nod[ll].radd+=x;
nod[rr].radd+=nod[u].radd;
nod[rr].ladd+=x;
nod[ll].s+=(nod[u].ladd+x)*nod[ll].len/2.0;
nod[rr].s+=(x+nod[u].radd)*nod[rr].len/2.0;
nod[u].ladd=nod[u].radd=0;
}
void updata(int u,int l,int r,int x,int y,double add1,double add2){
if(l==x&&r==y){
nod[u].s+=(add1+add2)*nod[u].len/2.0;
nod[u].ladd+=add1;nod[u].radd+=add2;
return;
}
push_down(u);
int mid=l+r>>1;
if(x>=mid)updata(rs,x,y,add1,add2);
else if(y<=mid)updata(ls,x,y,add1,add2);
else{
updata(ls,x,mid,add1,Q(x,add1,y,add2,mid));
updata(rs,mid,y,Q(x,add1,y,add2,mid),add2);
}
push_up(u);
}
double query(int u,int l,int r,int x,int y){
if(x==l&&r==y){ return nod[u].s;}
push_down(u);
int mid=l+r>>1;
if(x>=mid)return query(rs,x,y);
else if(y<=mid)return query(ls,x,y);
else return query(ls,x,mid)+query(rs,mid,y);
}
int main(){
init();
int T=1;
while(T--){
tot=cnt=ttot=0;
scanf("%d",&n);
char s[5];
for(int i=1;i<=n;i++){
scanf("%s",s);
if(s[0]=='Q'){
que[i].flag=0,scanf("%d%d",&que[i].a[1],&que[i].b[1]);//0是查询
cur[++cnt]=que[i].a[1],cur[++cnt]=que[i].b[1];
}
else {
que[i].flag=1;//1是多边形
scanf("%d",&que[i].n);
for(int j=1;j<=que[i].n;j++){
scanf("%d%d",&que[i].a[j],&que[i].b[j]);
que[i].Min=min(que[i].Min,que[i].b[j]);
cur[++cnt]=que[i].a[j];
}
}
}
front();
build(1,1,cnt);
for(int i=1;i<=tot;i++){
if(ne[i].id==24){
printf("%.3lf\n",query(1,1,cnt,lower_bound(cur+1,cur+1+cnt,ne[i].x1)-cur,lower_bound(cur+1,cur+1+cnt,ne[i].x2)-cur));
}
else {
updata(1,1,cnt,lower_bound(cur+1,cur+1+cnt,ne[i].x1)-cur,lower_bound(cur+1,cur+1+cnt,ne[i].x2)-cur,(double)ne[i].h1,(double)ne[i].h2);
}
}
}
return 0;
}