• 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
    ",query(1,pos1,pos2-1));
                }
            }
        }
    }
    View Code
  • 相关阅读:
    sdmenu js
    python 语言开发组合模块,为软件整合提供帮助
    星际二 地图制作过程
    mozilla
    虚拟机 装 ios
    jaxb之xjc编码问题
    抽象类注意事项(面试常常涉及)
    使用java6做webservice
    在linux上jaxb 工具的shell命令编写
    在Redhat 5.0 上安装Eclipse 3.6
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12535380.html
Copyright © 2020-2023  润新知