HDU3340 Rain in ACStar (线段树维护等差数列)

对于这题,首先我们要明确的一点是,直接求面积肯定是不行的,所以要转化求,我们发现,其实整个多边形的面积就是与x轴所形成的两个矩形的差

而矩形的面积就可以用(a+b)*h/2来做,h就是相邻的x的差,那么只需要维护上底和下底就行了,我们发现,其实只需要维护一个等差数列就行了,这点很巧妙

因为我们的y值区别其实就是线性的关系,另外我们要知道,两个等差数列的和也是等差数列,这样我们就可以用线段树维护区间求y了。

对于多边形,在上面的边应该加,在下面的边应该减,根据输入,其实就是x1<x2的要减,否则是加,所以我们维护四个值即可,一个是首项,一个是末项,一个是公差,一个是总面积

本题数据很大,所以需要离散化。这里需要注意的是,如果处理区间问题,那么在更新的时候需要更新l和r-1而不是r,因为我们维护的是区间,如果不这样,会在mid的时候漏掉一段。

比如经典的扫描线问题等,都是需要r-1的,而如果我们单纯维护的一段点的话,就不需要-1,这里需要对每个题进行讨论,显然这题是真正意义上维护区间的。

这题不存在覆盖之类的问题,这需要对题意仔细理解。另外,我们知道,对于普通的区间修改,修改的时候值是不变的,但是等差数列不一样,因为如果在中间断开,那么对于两边修改的值是不一样的

如果不理解这句话,可以根据我modify函数的代码进行理解。

#include<iostream>
#include<queue>
#include<map>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<string>
#include<cstring>
#include<set>
using namespace std;
typedef long long ll;
const int N=1e5+10;
struct qi{
    int l[6];
    int r[6];
    string s;
    int cnt;
}q[N];
struct node{
    int l,r;
    double sum;
    double d;
    double ld;
    double rd;
}tr[N<<2];
vector<int> num;
void pushup(int u){
    tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
}
double cal(int l,int r,double x,double y){
    int len=num[r]-num[l-1];
    return x+len*y;
}
void pushdown(int u){
    double add1=tr[u].ld,add2=tr[u].rd,step=tr[u].d;
    double tmp=cal(tr[u].l,(tr[u].l+tr[u].r)>>1,add1,step);
    tr[u<<1].ld+=add1,tr[u<<1].rd+=tmp,tr[u<<1].sum+=(num[tr[u<<1].r]-num[tr[u<<1].l-1])*(add1+tmp)/2,tr[u<<1].d+=step;
    tr[u<<1|1].ld+=tmp,tr[u<<1|1].rd+=add2,tr[u<<1|1].sum+=(num[tr[u<<1|1].r]-num[tr[u<<1|1].l-1])*(tmp+add2)/2,tr[u<<1|1].d+=step;
    tr[u].ld=tr[u].rd=tr[u].d=0;
}
void build(int u,int l,int r){
    if(l==r){
        tr[u]=(node){l,l,0,0,0,0};
    }
    else{
        tr[u]=(node){l,r};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
    }
}
void modify(int u,int l,int r,double y1,double y2,double x){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].ld+=y1;
        tr[u].rd+=y2;
        tr[u].d+=x;
        tr[u].sum+=(num[tr[u].r]-num[tr[u].l-1])*(y1+y2)/2;
        return ;
    }
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    double tmp=cal(l,mid,y1,x);
    if(l>mid){
        modify(u<<1|1,l,r,y1,y2,x);
    }
    else if(r<=mid){
        modify(u<<1,l,r,y1,y2,x);
    }
    else{
        modify(u<<1,l,mid,y1,tmp,x);
        modify(u<<1|1,mid+1,r,tmp,y2,x);
    }
    pushup(u);
}
double query(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r)
        return tr[u].sum;
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    double res=0;
    if(l<=mid)
        res=query(u<<1,l,r);
    if(r>mid)
        res+=query(u<<1|1,l,r);
    return res;
}
int find(int x){
    return lower_bound(num.begin(),num.end(),x)-num.begin()+1;
}
int main(){
    int i,j;
    int t;
    cin>>t;
    while(t--){
        int n;
        num.clear();
        cin>>n;
        for(i=1;i<=n;i++){
            string s;
            cin>>s;
            q[i].s=s;
            if(s=="R"){
                int x;
                cin>>x;
                q[i].cnt=x;
                for(j=0;j<x;j++){
                    scanf("%d%d",&q[i].l[j],&q[i].r[j]);
                    num.push_back(q[i].l[j]);
                }
            }
            else{
                scanf("%d%d",&q[i].l[0],&q[i].r[0]);
                    num.push_back(q[i].l[0]);
                    num.push_back(q[i].r[0]);
            }

        }
        sort(num.begin(),num.end());
        num.erase(unique(num.begin(),num.end()),num.end());
        build(1,1,num.size()-1);
        for(i=1;i<=n;i++){
            if(q[i].s=="R"){
                for(j=0;j<q[i].cnt;j++){
                    int x1=q[i].l[j],y1=q[i].r[j];
                    int x2=q[i].l[(j+1)%q[i].cnt],y2=q[i].r[(j+1)%q[i].cnt];
                    if(x1>x2){
                        swap(x1,x2);
                        swap(y1,y2);
                    }
                    else{
                        y1=-y1,y2=-y2;
                    }
                    double d=(1.0*y1-1.0*y2)/(1.0*x1-1.0*x2);
                    int pos1=find(x1);
                    int pos2=find(x2);
                    modify(1,pos1,pos2-1,y1,y2,d);
                }
            }
            else{
                int pos1=find(q[i].l[0]);
                int pos2=find(q[i].r[0]);
                printf("%.3f\n",query(1,pos1,pos2-1));
            }
        }
    }
}
View Code

 

posted @ 2020-03-20 22:24  朝暮不思  阅读(253)  评论(0编辑  收藏  举报