hdu3255线段树扫描线

题目链接

了解题意之后,没有思路。。参考了别人的博客,这个题目的解题思路就是维护分量,

将原来的一个长度分解成三个长度,然后加以维护,维护通过pushUp操作来完成,维

护的步骤按照价格的高低。

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=130010;//矩形个数
struct edge{
    int x1,x2,y,s;
    int f;//1入,-1出
    edge(){}
    edge(int _x1,int _x2,int _y,int _s,int _f)
    {
        x1=_x1,x2=_x2,y=_y,
            s=_s,f=_f;
    }
    bool operator <(const edge &e)
    {
        if(y!=e.y)return y<e.y;
        return f>e.f;
    }
};
struct price{
    int id,p;
    bool operator<(const price &prc)const
    {
        return p<prc.p;
    }
};
price P[5];
int nSgs;
edge Sgs[maxn*2];
int nX;
int X[maxn*2];
int len[maxn*4][4];
int cnt[maxn*4][4];
void build(int root,int l,int r)
{
    len[root][1]=len[root][2]=len[root][3]=0;
    cnt[root][1]=cnt[root][2]=cnt[root][3]=0;
    if(l==r)return;
    int mid=(l+r)/2;
    build(root*2,l,mid);
    build(root*2+1,mid+1,r);
}
//三个分量随着扫描线的变化
void pushUp(int root,int l,int r,int f,int p)
{
    if(cnt[root][3]){
        len[root][3]=X[r+1]-X[l];
        len[root][2]=0;
        len[root][1]=0;
    }
    else if(cnt[root][2]){
        len[root][3]=len[root*2][3]+len[root*2+1][3];
        len[root][2]=X[r+1]-X[l]-len[root][3];
        len[root][1]=0;
    }
    else if(cnt[root][1]){
        len[root][3]=len[root*2][3]+len[root*2+1][3];
        len[root][2]=len[root*2][2]+len[root*2+1][2];
        len[root][1]=X[r+1]-X[l]-len[root][3]-len[root][2];
    }
    else {
        len[root][3]=len[root*2][3]+len[root*2+1][3];
        len[root][2]=len[root*2][2]+len[root*2+1][2];
        len[root][1]=len[root*2][1]+len[root*2+1][1];
    }
}
void update(int root,int L,int R,int f,int p,int l,int r)
{
    if(L<=l&&r<=R){
        cnt[root][p]+=f;
        pushUp(root,l,r,f,p);
        return;
    }
    int mid=(l+r)/2;
    if(mid>=L)update(root*2,L,R,f,p,l,mid);
    if(mid<R)update(root*2+1,L,R,f,p,mid+1,r);
    pushUp(root,l,r,f,p);
}
int bin(int k,int X[],int n)
{
    int l=0,r=n-1,mid;
    while(l<=r){
        mid=(l+r)/2;
        if(X[mid]==k)return mid;
        else if(X[mid]>k)r=mid-1;
        else l=mid+1;
    }
    return -1;
}
int myUnique(int X[],int n)//哈希之前要去重
{
    int p=1;
    for(int i=1;i<n;i++){
        if(X[i]!=X[i-1])X[p++]=X[i];
    }
    return p;
}
int main()
{
    //freopen("in.txt","r",stdin);
    int T;
    int p=0;
    scanf("%d",&T);
    while(T--){
        p++;
        nX=0,nSgs=0;
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            P[i].id=i;
            scanf("%d",&P[i].p);
        }
        sort(P+1,P+1+m);
        while(n--){
            int x1,y1,x2,y2,id;
            scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&id);
            X[nX++]=x1,X[nX++]=x2;
            int k;
            for(int i=1;i<=m;i++){
                if(P[i].id==id)k=i;
            }
            Sgs[nSgs++]=edge(x1,x2,y1,k,1);
            Sgs[nSgs++]=edge(x1,x2,y2,k,-1);
        }
        sort(X,X+nX);
        sort(Sgs,Sgs+nSgs);
        nX=myUnique(X,nX);
        build(1,0,nX-1);
        long long tot=0;
        for(int i=0;i<nSgs-1;i++){
            int l=bin(Sgs[i].x1,X,nX);
            int r=bin(Sgs[i].x2,X,nX)-1;
            if(l<=r)
            update(1,l,r,Sgs[i].f,Sgs[i].s,0,nX-1);
            int l1=len[1][1],l2=len[1][2],l3=len[1][3];
            tot+=((long long)(l1*P[1].p+l2*P[2].p+l3*P[3].p))*(Sgs[i+1].y-Sgs[i].y);
        }
        printf("Case %d: %lld
",p,tot);
    }
    //while(1);
}
View Code

参考资料

http://www.cnblogs.com/lxjshuju/p/6956796.html

原文地址:https://www.cnblogs.com/MalcolmMeng/p/8460083.html