zoukankan      html  css  js  c++  java
  • 线段树题集

    hdu1199-Color the Ball(区间覆盖)

    /*
    题意:有无限个球排成一行,刚开始是黑色,然后他可以给一段区间染成
    黑色或白色,最后要求找出最长连续白球序列,如果有多解,输出最左边
    的,不存在输出Oh, my god
    
    解析:因为是无限大,所以要离散化,我为了方便,将坐标扩大了3倍
    每次插入区间的时候插入[L,R+1],插入完之后整个压下去,记录每个位置
    是白色还是黑色,然后更新答案即可,具体细节见代码。
    */
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<sstream>
    #include<utility>
    #include<iterator>
    using namespace std;
    const int INF=1e9+7;
    const double eps=1e-7;
    typedef __int64 LL;
    const int maxn=2005;
    int N,Size;
    struct node
    {
        int L,R;
        char C[2];
    }Nod[maxn];
    vector<int> ve;
    struct Tree
    {
        int le,ri,lazy;
    }tree[3*4*2*maxn];
    int mark[3*2*maxn];
    void GetPos()
    {
        sort(ve.begin(),ve.end());
        ve.erase(unique(ve.begin(),ve.end()),ve.end());
        for(int i=0;i<N;i++)   //离散化
        {
            node& t=Nod[i];
            t.L=lower_bound(ve.begin(),ve.end(),t.L)-ve.begin();
            t.L*=3;  //扩大3倍
            t.R=lower_bound(ve.begin(),ve.end(),t.R)-ve.begin();
            t.R*=3;
        }
    }
    void build_tree(int id,int le,int ri)
    {
        Tree& e=tree[id];
        e.le=le,e.ri=ri,e.lazy=-1;
        if(le==ri) return;
        int mid=(le+ri)/2;
        build_tree(id*2,le,mid);
        build_tree(id*2+1,mid+1,ri);
        return;
    }
    void pushdown(int id)
    {
        if(tree[id].lazy!=-1) 
        {
            tree[id*2].lazy=tree[id*2+1].lazy=tree[id].lazy;
            tree[id].lazy=-1;
        }
    }
    void update(int id,int x,int y,int c)
    {
        Tree& e=tree[id];
        int le=e.le,ri=e.ri;
        if(x<=le&&ri<=y){ e.lazy=c; return; }
        pushdown(id);
        int mid=(le+ri)/2;
        if(x<=mid) update(id*2,x,y,c);
        if(y>mid)  update(id*2+1,x,y,c);
        return;
    }
    void query(int id)
    {
        Tree& e=tree[id];
        int le=e.le,ri=e.ri;
        if(le==ri)
        {
            mark[le]=abs(e.lazy);
            return;
        }
        pushdown(id);
        query(id*2);
        query(id*2+1);
        return;
    }
    int GetAns(int a,int b,int& ra,int& rb)
    {
        ra=ve[a/3],rb=ve[(b+1)/3];
        if(a%3!=0) ra++; //不为0说明左端点的这个位置被占了,要加1
        if(b%3!=1) rb--; //不为1说明右端点的这个位置被占了,要减1
        return rb-ra+1;
    }
    void solve()
    {
        Size=ve.size()-1;
        build_tree(1,0,3*Size+1); //建树
        for(int i=0;i<N;i++)
        {
            node& t=Nod[i];
            if(t.C[0]=='w') update(1,t.L,t.R+1,0);  //0代表白色,
                                 //R+1是用于后面判断右端点是否被覆盖
            else update(1,t.L,t.R+1,1);  //1代表黑色
        }
        query(1); //整个压下去
        int ret=0;
        int pre=-1;
        vector<pair<int,int> > V;
        V.clear();
    
        for(int i=0;i<=3*Size+1;i++)
        {
            if(mark[i]) //被标记为黑色
            {
                if(pre!=-1) V.push_back(make_pair(pre,i-1)); //找到一段
                pre=-1;
                continue;
            }
            if(pre==-1) pre=i;//当前是白色起点位置,之前是黑色
        }
        if(pre!=-1) V.push_back(make_pair(pre,3*Size+1)); //最后还有一段
        int ansa=-1,ansb=-1;
        for(int i=0;i<V.size();i++)
        {
            int a=V[i].first,b=V[i].second;
            int ra,rb;
            int tt=GetAns(a,b,ra,rb); 
            if(ret<tt){ ret=tt; ansa=ra,ansb=rb; } //找答案
        }
        if(ansa==-1) printf("Oh, my god
    ");  //无解
        else printf("%d %d
    ",ansa,ansb);   //打印两个位置
    }
    int main()
    {
        while(scanf("%d",&N)!=EOF)
        {
            ve.clear();
            for(int i=0;i<N;i++)
            {
               scanf("%d%d%s",&Nod[i].L,&Nod[i].R,Nod[i].C);
               if(Nod[i].L>Nod[i].R) swap(Nod[i].L,Nod[i].R);//以防万一才写的
               ve.push_back(Nod[i].L); ve.push_back(Nod[i].R);
            }
            GetPos();
            solve();
        }
        return 0;
    }
    View Code

    hdu1255- 覆盖的面积(扫描线+矩形多重覆盖)

    /*
    题意:计算至少覆盖两次的区域的面积
    
    解析:裸的扫描线,但是是超过2次覆盖,这里再增加一个
    ss这个变量,代表两次及以上覆盖的长度,我也是看别人
    博客做的,固定的模式。。。
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    typedef __int64 LL; 
    const int maxn=2005; 
    struct node 
    { 
        double L,R,H; 
        int c; 
        node(double L=0,double R=0,double H=0,int c=1) 
        :L(L),R(R),H(H),c(c){} 
        bool operator < (const node& t) const
        { 
            return H<t.H; 
        } 
    }Nod[maxn]; 
    int N,num; 
    double A[maxn]; 
    struct Tree 
    { 
        int le,ri,d; 
        double s,ss; 
    }tree[8*maxn]; 
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le,e.ri=ri,e.d=0; 
        e.s=0,e.ss=0; 
        if(le==ri) return; 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        return; 
    } 
    void pushup(int id) 
    { 
        Tree& fa=tree[id]; 
        Tree& lson=tree[id*2]; 
        Tree& rson=tree[id*2+1]; 
        int le=fa.le,ri=fa.ri; 
        if(fa.d) fa.s=A[ri+1]-A[le]; 
        else if(le==ri) fa.s=0; 
        else fa.s=lson.s+rson.s; 
        if(fa.d>1) fa.ss=A[ri+1]-A[le]; 
        else if(le==ri) fa.ss=0; 
        else if(fa.d==1) fa.ss=lson.s+rson.s; 
        else fa.ss=lson.ss+rson.ss; 
    } 
    void update(int id,int x,int y,int c) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x==le&&ri==y) 
        { 
            e.d+=c; 
            pushup(id); 
            return; 
        } 
        int mid=(le+ri)/2; 
        if(y<=mid) update(id*2,x,y,c); 
        else if(x>mid) update(id*2+1,x,y,c); 
        else
        { 
            update(id*2,x,mid,c); 
            update(id*2+1,mid+1,y,c); 
        } 
        pushup(id); 
        return; 
    } 
    double solve() 
    { 
        sort(Nod+1,Nod+num+1); 
        sort(A+1,A+num+1); 
        int k=1; 
        for(int i=2;i<=num;i++) if(A[i]!=A[k]) A[++k]=A[i]; //去重
        build_tree(1,1,k); 
        double ret=0; 
        for(int i=1;i<num;i++) 
        { 
            node& t=Nod[i]; 
            int x=lower_bound(A+1,A+k+1,t.L)-A; //下标
            int y=lower_bound(A+1,A+k+1,t.R)-A-1; 
            update(1,x,y,t.c); //更新
            ret+=tree[1].ss*(Nod[i+1].H-Nod[i].H); 
        } 
        return ret; 
    } 
    int main() 
    { 
        int T; 
        scanf("%d",&T); 
        while(T--) 
        { 
            scanf("%d",&N); 
            num=0; 
            double x1,y1,x2,y2; 
            for(int i=1;i<=N;i++) 
            { 
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); //输入坐标
                Nod[++num]=node(x1,x2,y1,1);  //增加下边
                A[num]=x1; //为了离散化所用
                Nod[++num]=node(x1,x2,y2,-1); //增加上边
                A[num]=x2; 
            } 
            printf("%.2lf
    ",solve()); 
        } 
        return 0; 
    }
    View Code

    hdu3074-Multiply game(成段更新取乘积)

    /*
    题意:计算一段区间的乘积模上1000000007
    
    解析:裸的线段树成段更新,计算的时候乘积取模就可以了
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    typedef __int64 LL; 
    #define fa tree[id] 
    #define lson tree[id*2] 
    #define rson tree[id*2+1] 
    const int maxn=50005; 
    const LL mod=1e9+7; 
    struct Tree 
    { 
        int le,ri; 
        LL sum; 
    }tree[4*maxn]; 
    void pushup(int id){ fa.sum=(lson.sum*rson.sum)%mod; } 
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le,e.ri=ri; 
        if(le==ri) 
        { 
            scanf("%I64d",&e.sum); 
            return; 
        } 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        pushup(id); 
        return; 
    } 
    void update(int id,int k,LL v) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(le==ri) { e.sum=v%mod; return; } 
        int mid=(le+ri)/2; 
        if(k<=mid) update(id*2,k,v); 
        else update(id*2+1,k,v); 
        pushup(id); 
        return; 
    } 
    LL query(int id,int x,int y) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) return e.sum; 
        LL ret=1; 
        int mid=(le+ri)/2; 
        if(x<=mid) ret*=query(id*2,x,y); 
        if(y>mid)  ret*=query(id*2+1,x,y); 
        return ret%mod; 
    } 
    int main() 
    { 
        int T; 
        scanf("%d",&T); 
        while(T--) 
        { 
            int N; 
            scanf("%d",&N); 
            build_tree(1,1,N); 
            int M; 
            scanf("%d",&M); 
            int op,x,y; 
            for(int k=1;k<=M;k++) 
            { 
                scanf("%d%d%d",&op,&x,&y); 
                if(op==0) printf("%I64d
    ",query(1,x,y)); 
                else update(1,x,(LL)y); 
            } 
        } 
        return 0; 
    } 
    View Code

    hdu3255-Farming(扫描线)

    /*
    题意:有N种不同的蔬菜,每种蔬菜有一个价格,给出M
    块矩形田地以及这块田地上种植的是哪种蔬菜。覆盖的
    地方价格最高的那种蔬菜会生存下去。问最多可以获得
    多大的收益。
    
    解析:对价格排个序,然后开始枚举price[i],把种植价格
    大于等于price[i]的田地加进去进行扫描线,答案加上面
    积乘上price[i]-price[i-1]的差值。
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    typedef __int64 LL; 
    #define fa tree[id] 
    #define lson tree[id*2] 
    #define rson tree[id*2+1] 
    #define e tree[id] 
    const int maxn=60005; 
    struct Po 
    { 
        int x1,y1,x2,y2,val; 
        Po(int x1=0,int y1=0,int x2=0,int y2=0,int val=0) 
        :x1(x1),y1(y1),x2(x2),y2(y2),val(val){} 
    }P[maxn]; 
    struct node 
    { 
        int L,R,H,s; 
        node(int L=0,int R=0,int H=0,int s=1) 
        :L(L),R(R),H(H),s(s){} 
        bool operator < (const node& t) const
        { 
            return H<t.H; 
        } 
    }Nod[maxn]; 
    struct Tree 
    { 
        int le,ri,c,sum; 
    }tree[4*maxn]; 
    int N,M,num,price[4],A[maxn]; 
    void AddLine(Po& t) 
    { 
        Nod[++num]=node(t.x1,t.x2,t.y1,1); 
        A[num]=t.x1; 
        Nod[++num]=node(t.x1,t.x2,t.y2,-1); 
        A[num]=t.x2; 
    } 
    void build_tree(int id,int le,int ri) 
    { 
        e.le=le,e.ri=ri,e.c=e.sum=0; 
        if(le==ri) return; 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        return; 
    } 
    void pushup(int id) 
    { 
        int le=fa.le,ri=fa.ri; 
        if(fa.c) fa.sum=A[ri+1]-A[le]; 
        else if(le==ri) fa.sum=0; 
        else fa.sum=lson.sum+rson.sum; 
    } 
    void update(int id,int x,int y,int c) 
    { 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) 
        { 
            e.c+=c; 
            pushup(id); 
            return; 
        } 
        int mid=(le+ri)/2; 
        if(x<=mid) update(id*2,x,y,c); 
        if(y>mid)  update(id*2+1,x,y,c); 
        pushup(id); 
        return; 
    } 
    LL Get() //扫描线
    { 
        sort(Nod+1,Nod+num+1); 
        sort(A+1,A+num+1); 
        int k=1; 
        for(int i=2;i<=num;i++) if(A[i]!=A[k]) A[++k]=A[i]; //去重
        build_tree(1,1,k); //建树
        LL ret=0; 
        for(int i=1;i<num;i++) //模板
        { 
            node& t=Nod[i]; 
            int x=lower_bound(A+1,A+k+1,t.L)-A; 
            int y=lower_bound(A+1,A+k+1,t.R)-A-1; 
            if(x>y) continue; 
            update(1,x,y,t.s); 
            ret+=(LL)tree[1].sum*(Nod[i+1].H-Nod[i].H); 
        } 
        return ret; 
    } 
    LL solve() 
    { 
        price[0]=0; 
        sort(price+1,price+M+1); 
        LL ret=0; 
        for(int i=1;i<=M;i++) //依次加起来
        { 
            num=0; 
            for(int j=1;j<=N;j++) 
                if(P[j].val>=price[i]) AddLine(P[j]); //增加这条边 
            ret+=Get()*(price[i]-price[i-1]); //把差值加上
        } 
        return ret; 
    } 
    int main() 
    { 
        int T,Case=0; 
        scanf("%d",&T); 
        while(T--) 
        { 
            scanf("%d%d",&N,&M); 
            for(int i=1;i<=M;i++) scanf("%d",&price[i]); 
            int x1,y1,x2,y2,type; 
            for(int i=1;i<=N;i++) 
            { 
                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&type); 
                P[i]=Po(x1,y1,x2,y2,price[type]); 
            } 
            printf("Case %d: %I64d
    ",++Case,solve()); 
        } 
        return 0; 
    } 
    View Code

    hdu3642-Get The Treasury(扫描线+三重覆盖)

    /*
    题意:求覆盖至少三次的体积
    
    解析:离散化高度,扫描线求面积,覆盖三次
    增加3个变量s,ss,sss,分别记录至少覆盖一次,两次,三次
    的区间长度
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    typedef long long LL; 
    #define fa tree[id] 
    #define lson tree[id*2] 
    #define rson tree[id*2+1] 
    #define e tree[id] 
    const int maxn=2005; 
    int N,num; 
    struct Point 
    { 
        int x1,y1,z1,x2,y2,z2; 
        Point(int x1=0,int y1=0,int z1=0,int x2=0,int y2=0,int z2=0) 
        :x1(x1),y1(y1),z1(z1),x2(x2),y2(y2),z2(z2){} 
    }P[maxn]; 
    struct node 
    { 
        int L,R,H,s; 
        node(int L=0,int R=0,int H=0,int s=0) 
        :L(L),R(R),H(H),s(s){} 
        bool operator < (const node& t) const
        { 
            return H<t.H; 
        } 
    }Nod[maxn]; 
    struct Tree 
    { 
        int le,ri,c; 
        int s,ss,sss; 
    }tree[4*maxn]; 
    int A[maxn]; 
    void AddLine(Point& p) 
    { 
        Nod[++num]=node(p.x1,p.x2,p.y1,1); 
        A[num]=p.x1; 
        Nod[++num]=node(p.x1,p.x2,p.y2,-1); 
        A[num]=p.x2; 
    } 
    void build_tree(int id,int le,int ri) 
    { 
        e.le=le,e.ri=ri,e.s=e.ss=e.sss=0,e.c=0; 
        if(le==ri) return; 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        return; 
    } 
    void pushup(int id) //这个地方是重点
    { 
        int le=fa.le,ri=fa.ri; 
        if(fa.c) fa.s=A[ri+1]-A[le]; 
        else if(le==ri) fa.s=0; 
        else fa.s=lson.s+rson.s; 
      
        if(fa.c>=2) fa.ss=A[ri+1]-A[le]; 
        else if(le==ri) fa.ss=0; 
        else if(fa.c==1) fa.ss=lson.s+rson.s; 
        else fa.ss=lson.ss+rson.ss; 
      
        if(fa.c>=3) fa.sss=A[ri+1]-A[le]; 
        else if(le==ri) fa.sss=0; 
        else if(fa.c==2) fa.sss=lson.s+rson.s; 
        else if(fa.c==1) fa.sss=lson.ss+rson.ss; 
        else fa.sss=lson.sss+rson.sss; 
    } 
    void update(int id,int x,int y,int c) 
    { 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) 
        { 
            e.c+=c; 
            pushup(id); 
            return; 
        } 
        int mid=(le+ri)/2; 
        if(x<=mid) update(id*2,x,y,c); 
        if(y>mid)  update(id*2+1,x,y,c); 
        pushup(id); 
        return; 
    } 
    LL Get()   //扫描线模板
    { 
        if(num<6) return 0; 
        sort(Nod+1,Nod+num+1); 
        sort(A+1,A+num+1); 
        int k=1; 
        for(int i=2;i<=num;i++) if(A[i]!=A[k]) A[++k]=A[i]; 
        build_tree(1,1,k-1); 
        int x,y; 
        LL ret=0; 
        for(int i=1;i<num;i++) 
        { 
            node& t=Nod[i]; 
            x=lower_bound(A+1,A+k+1,t.L)-A; 
            y=lower_bound(A+1,A+k+1,t.R)-A-1; 
            update(1,x,y,t.s); 
            ret+=(LL)tree[1].sss*(Nod[i+1].H-Nod[i].H); 
        } 
        return ret; 
    } 
    int B[maxn]; 
    LL solve() 
    { 
        LL ret=0; 
        sort(B+1,B+num+1); 
        int k=1; 
        for(int i=2;i<=num;i++) if(B[i]!=B[k]) B[++k]=B[i]; //离散化高度
        for(int i=2;i<=k;i++) //枚举
        { 
            num=0; 
            for(int j=1;j<=N;j++) 
            { 
                Point& p=P[j]; 
                if(p.z1<B[i]&&p.z2>=B[i]) AddLine(p); //把边加进去
            } 
            LL add=Get(); 
            ret+=add*((LL)B[i]-B[i-1]); //加上这一层的体积
        } 
        return ret; 
    } 
    int main() 
    { 
        int T,Case=0; 
        scanf("%d",&T); 
        while(T--) 
        { 
            scanf("%d",&N); 
            int x1,x2,y1,y2,z1,z2; 
            num=0; 
            for(int i=1;i<=N;i++) 
            { 
                scanf("%d%d%d%d%d%d",&x1,&y1,&z1,&x2,&y2,&z2); 
                P[i]=Point(x1,y1,z1,x2,y2,z2); //增加一个长方体
                B[++num]=z1; 
                B[++num]=z2; 
            } 
            LL ans=solve(); 
            printf("Case %d: %lld
    ",++Case,ans); 
        } 
        return 0; 
    } 
    View Code

    hdu3911-Black And White(线段树01翻转)

    /*
    题意:可以将一段区间黑变成白,白变成黑,查询时问最长连续黑色的
    长度是多少
    
    解析:线段树区间合并,设置wll(白色左边连续的长度),wrl(白色右边连续的长度)
    wml(白色最长的连续长度),bll(黑色左边连续的长度),brl(黑色右边连续的长度)
    bml(黑色最长的连续长度)。没次pushup都要更新这些值,具体细节见代码。
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    typedef __int64 LL; 
    #define fa  tree[id] 
    #define lson tree[id*2] 
    #define rson tree[id*2+1] 
    const int maxn=100005; 
    struct Tree 
    { 
        int le,ri,len,c,d; 
        int wll,wrl,wml; 
        int bll,brl,bml; 
        void init() 
        { 
            bll=brl=bml=len*c; 
            wll=wrl=wml=len*(c^1); 
        } 
        void f() 
        { 
            swap(bll,wll); swap(brl,wrl); swap(bml,wml); //黑白交换
        } 
    }tree[4*maxn]; 
    int N,M; 
    void pushup(int id) 
    { 
        fa.bll=lson.bll; 
        if(fa.bll==lson.len) fa.bll+=rson.bll; //延伸到右边去
        fa.brl=rson.brl; 
        if(fa.brl==rson.len) fa.brl+=lson.brl; //延伸到左边去
        fa.bml=max(lson.bml,rson.bml);         //更新最大值
        fa.bml=max(fa.bml,max(fa.bll,fa.brl)); 
        fa.bml=max(fa.bml,lson.brl+rson.bll); 
      
        fa.wll=lson.wll;                       //同理
        if(fa.wll==lson.len) fa.wll+=rson.wll; 
        fa.wrl=rson.wrl; 
        if(fa.wrl==rson.len) fa.wrl+=lson.wrl; 
        fa.wml=max(lson.wml,rson.wml); 
        fa.wml=max(fa.wml,max(fa.wll,fa.wrl)); 
        fa.wml=max(fa.wml,lson.wrl+rson.wll); 
    } 
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le,e.ri=ri,e.len=ri-le+1,e.d=0; 
        if(le==ri) 
        { 
            scanf("%d",&e.c); 
            e.init(); 
            return; 
        } 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        pushup(id); 
    } 
    void pushdown(int id) 
    { 
        if(fa.d) 
        { 
            lson.d^=1; 
            rson.d^=1; 
            lson.f(),rson.f(); 
            fa.d=0; 
        } 
    } 
    void update(int id,int x,int y) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) 
        { 
            e.d^=1; //异或操作 
            e.f(); 
            return; 
        } 
        pushdown(id); 
        int mid=(le+ri)/2; 
        if(x<=mid) update(id*2,x,y); 
        if(y>mid)  update(id*2+1,x,y); 
        pushup(id); 
        return; 
    } 
    int query(int id,int x,int y) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) return e.bml; 
        pushdown(id); 
        int mid=(le+ri)/2; 
        int ret=0; 
        if(x<=mid) ret=max(ret,query(id*2,x,y)); //查询左边
        if(y>mid)  ret=max(ret,query(id*2+1,x,y)); //右边
        if(x<=mid&&y>mid) ret=max(ret,min(mid-x+1,lson.brl)+min(y-mid,rson.bll));//中间合并的一段 
        pushup(id); 
        return ret; 
    } 
    int main() 
    { 
        while(scanf("%d",&N)!=EOF) 
        { 
            build_tree(1,1,N); 
            scanf("%d",&M); 
            int op,x,y; 
            for(int k=1;k<=M;k++) 
            { 
                scanf("%d%d%d",&op,&x,&y); 
                if(op==1) update(1,x,y); //更新
                else printf("%d
    ",query(1,x,y)); //查询 
            } 
        } 
        return 0; 
    } 
    View Code

    poj1177-Picture(扫描线求周长)

    /*
    题意:求周长
    
    解析:x轴方向来一遍扫描线,y轴方向来一遍
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e8+7; 
    const double eps=1e-7; 
    typedef __int64 LL; 
    const int maxn=20005; 
    int N,num; 
    struct node 
    { 
           int L,R,H,s; 
           node(int L=0,int R=0,int H=0,int s=1) 
           :L(L),R(R),H(H),s(s){} 
           bool operator < (const node& t) const
           { 
               return H<t.H; 
           } 
    }Row[maxn],Col[maxn]; 
    int RV[maxn],CV[maxn]; 
    struct Tree 
    { 
        int le,ri,lazy,d; 
    }tree[4*maxn]; 
    int ans; 
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le,e.ri=ri,e.d=-1; 
        if(le==ri) { e.d=0; return; } 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        return; 
    } 
    int GetAns(int a,int b,int type) 
    { 
        if(type==0) return RV[b]-RV[a]; 
        else return CV[b]-CV[a]; 
    } 
    void pushdown(int id) 
    { 
        Tree& fa=tree[id]; 
        Tree& lson=tree[id*2]; 
        Tree& rson=tree[id*2+1]; 
        if(fa.d!=-1) 
        { 
            lson.d=rson.d=fa.d; 
            fa.d=-1; 
        } 
    } 
    void pushup(int id) 
    { 
        Tree& fa=tree[id]; 
        Tree& lson=tree[id*2]; 
        Tree& rson=tree[id*2+1]; 
        if(lson.d==-1||rson.d==-1) fa.d=-1; 
        else if(lson.d!=rson.d) fa.d=-1; 
        else fa.d=lson.d; 
      
    } 
    void update(int id,int x,int y,int c,int type) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y&&e.d!=-1) 
        { 
            if(e.d==0&&c==1) ans+=GetAns(le,ri+1,type); 
            else if(e.d==1&&c==-1) ans+=GetAns(le,ri+1,type); 
            e.d+=c; 
            return; 
        } 
        pushdown(id); 
        int mid=(le+ri)/2; 
        if(x<=mid) update(id*2,x,y,c,type); 
        if(y>mid)  update(id*2+1,x,y,c,type); 
        pushup(id); 
        return; 
    } 
    int Get(node A[],int B[],int type) //type是类型,指的是行或者列
    { 
        sort(A+1,A+num+1); 
        sort(B+1,B+num+1); 
        int k=1; 
        for(int i=2;i<=num;i++) if(B[i]!=B[k]) B[++k]=B[i]; 
        build_tree(1,1,k); 
        int ret=0; 
        for(int i=1;i<=num;i++) 
        { 
            node& e=A[i]; 
            int x=lower_bound(B+1,B+k+1,e.L)-B; 
            int y=lower_bound(B+1,B+k+1,e.R)-B-1; 
            ans=0; 
            if(x>y) continue; 
            update(1,x,y,e.s,type); 
            ret+=ans; 
        } 
        return ret; 
    } 
    int solve() 
    { 
        int ret=0; 
        ret+=Get(Row,RV,0); //行方向
        ret+=Get(Col,CV,1); //列方向
        return ret; 
    } 
    int main() 
    { 
        while(scanf("%d",&N)!=EOF) 
        { 
            if(N==0) { printf("0
    "); continue; } 
            num=0; 
            for(int i=1;i<=N;i++) 
            { 
                int x1,y1,x2,y2; 
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2); 
                ++num; 
                Row[num]=node(x1,x2,y1,1);  //
                Col[num]=node(y1,y2,x1,1);  //
                RV[num]=x1; 
                CV[num]=y1; 
                ++num; 
                Row[num]=node(x1,x2,y2,-1); 
                Col[num]=node(y1,y2,x2,-1); 
                RV[num]=x2; 
                CV[num]=y2; 
            } 
            printf("%d
    ",solve()); 
        } 
      
        return 0; 
    } 
    View Code

    poj2777-Count Color(线段树+状态压缩)

    /*
    题意:给一段区间染色,颜色最多30种,查询一段区间有多少种颜色
    
    解析:状态压缩,增加S变量,如果哪种颜色被染了,则对应的二进制位为1
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    const int maxn=100005; 
    typedef __int64 LL; 
    struct Tree 
    { 
        int le,ri,lazy; 
        LL S; 
    }tree[4*maxn]; 
    int L,T,O; 
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le,e.ri=ri,e.S=2,e.lazy=-1; //S=2代表染了1这种颜色
        if(le==ri) return; 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        return; 
    } 
    void pushdown(int id) 
    { 
        if(tree[id].lazy!=-1) //延迟更新
        { 
            tree[id*2].lazy=tree[id*2+1].lazy=tree[id].lazy; 
            tree[id*2].S=tree[id*2+1].S=tree[id].S; 
            tree[id].lazy=-1; 
        } 
    } 
    void pushup(int id) 
    { 
        tree[id].S=tree[id*2].S | tree[id*2+1].S; //或运算
    } 
    void update(int id,int x,int y,int c) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y){ e.lazy=c; e.S=(LL)1<<c; return; } //染c色
        pushdown(id); 
        int mid=(le+ri)/2; 
        if(x<=mid) update(id*2,x,y,c); 
        if(y>mid)  update(id*2+1,x,y,c); 
        pushup(id); 
        return; 
    } 
    LL query(int id,int x,int y) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) return e.S; 
        pushdown(id); 
        int mid=(le+ri)/2; 
        LL ret=0; 
        if(x<=mid) ret|=query(id*2,x,y); 
        if(y>mid)  ret|=query(id*2+1,x,y); 
        pushup(id); 
        return ret; 
    } 
    int main() 
    { 
        scanf("%d%d%d",&L,&T,&O); 
        char op[2]; 
        int x,y,c; 
        build_tree(1,1,L); 
        while(O--) 
        { 
            scanf("%s",op); 
            if(op[0]=='C') 
            { 
                scanf("%d%d%d",&x,&y,&c); 
                update(1,x,y,c); 
            } 
            else
            { 
                scanf("%d%d",&x,&y); 
                if(x>y) swap(x,y); 
                LL S=query(1,x,y); 
                int ans=0; 
                while(S) //计算有多少种颜色
                { 
                    if(S&1) ans++;  
                    S>>=1; 
                } 
                printf("%d
    ",ans); 
            } 
        } 
        return 0; 
    } 
    View Code

    poj2828-Buy Tickets(线段树查询空位)

    /*
    题意:排队,但是可以插队,一个人来了可以插到第i个人之后
    0代表柜台,问最后的队伍顺序。
    
    解析:一开始建树时每一段都是空的,所以大小就是区间长度,
    从后面往前面插入,如果左边位置足够,则插到左边,否则右边
    找到插入位置后,空位减1
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    typedef __int64 LL; 
    const int maxn=200005; 
    int N,ans[maxn]; 
    int pos[maxn],val[maxn]; 
    struct Tree 
    { 
        int le,ri; 
        int num; 
    }tree[4*maxn]; 
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le,e.ri=ri; 
        e.num=ri-le+1;     //一开始都是空的
        if(le==ri) return; 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        return; 
    } 
    void update(int id,int p,int v) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(le==ri){ e.num--; ans[le]=v; return; } //插入进去,空间减1
        Tree& lson=tree[id*2]; 
        Tree& rson=tree[id*2+1]; 
        if(lson.num>=p) update(id*2,p,v);  //左边足够,则插到左边
        else update(id*2+1,p-lson.num,v);  //否则右边
        e.num=lson.num+rson.num;           //更新
        return; 
    } 
    int main() 
    { 
        while(scanf("%d",&N)!=EOF) 
        { 
            for(int i=0;i<N;i++) scanf("%d%d",&pos[i],&val[i]); //输入
            build_tree(1,0,N-1);   //建树
            for(int i=N-1;i>=0;i--) update(1,pos[i]+1,val[i]); //插入到第Pos[i]+1的位置 
            for(int i=0;i<N;i++) //输出
            { 
                if(i) printf(" "); 
                printf("%d",ans[i]); 
            } 
            printf("
    "); 
        } 
        return 0; 
    } 
    View Code

    poj3225-Help with Intervals(线段树+区间异或)

    /*
    题意:给出了几种集合运算,每次操作对一段区间进行其中的一种运算
    输出最后被覆盖的区间段,要注意开区间与闭区间
    
    解析:注意一下每种运算如何修改区间的值,在线段树里再增加两个变量
    d(整个区间的值),c(是否需要异或),具体细节见代码。
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    typedef __int64 LL; 
    #define fa tree[id] 
    #define lson tree[id*2] 
    #define rson tree[id*2+1] 
    #define e tree[id] 
    const int maxn=140000; 
    struct Tree 
    { 
        int le,ri,d,c; //d是区间的值,c代表是否需要异或
        void UpXor() 
        { 
            if(d!=-1) d^=1; //是整个连续相同的
            else c^=1; //懒惰标记异或
        } 
    }tree[4*maxn]; 
    void build_tree(int id,int le,int ri) 
    { 
        e.le=le,e.ri=ri,e.d=0,e.c=0; 
        if(le==ri) return; 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        return; 
    } 
    inline void pushdown(int id) 
    { 
        if(fa.d!=-1) 
        { 
            lson.d=rson.d=fa.d; 
            lson.c=rson.c=0; 
            fa.d=-1; 
        } 
        if(fa.c) 
        { 
           lson.UpXor(); 
           rson.UpXor(); 
           fa.c=0; 
        } 
    } 
    inline void Link(int id,char op) 
    { 
        if(op=='U') fa.d=1,fa.c=0;  //并集
        else if(op=='D') fa.d=0,fa.c=0; //差集S-T
        else if(op=='C'||op=='S') fa.UpXor(); //异或
    } 
    void update(int id,int x,int y,char op) 
    { 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) { Link(id,op); return; } 
        pushdown(id); 
        int mid=(le+ri)/2; 
        if(x<=mid) update(id*2,x,y,op); //左边可更新
        else if(op=='I'||op=='C') lson.d=lson.c=0;  //如果是交集或者是差集T-S,左边都要置为0
        if(y>mid) update(id*2+1,x,y,op);  //右边同理
        else if(op=='I'||op=='C') rson.d=rson.c=0; 
        return; 
    } 
    int mark[maxn]; //标记某位置是否被占
    vector<pair<int,int> > ve; 
    void query(int id) 
    { 
        if(e.le==e.ri) { mark[e.le]=e.d; return; } //一直压到叶子节点
        pushdown(id); 
        query(id*2); 
        query(id*2+1); 
        return; 
    } 
    int main() 
    { 
        char op,a,b; 
        int x,y; 
        build_tree(1,0,131070); //扩大了2倍
        while(scanf("%c %c%d,%d%c",&op,&a,&x,&y,&b)!=EOF) 
        { 
            getchar(); 
            x*=2; y*=2; //乘2
            if(a=='(') x++;  //不是实区间加1 
            if(b==')') y--; 
            if(x>y) //区间为空
            { 
                if(op=='I'||op=='C') tree[1].c=tree[1].d=0; 
                continue; 
            } 
            update(1,x,y,op); //更新 
        } 
        memset(mark,0,sizeof(mark)); 
        query(1); //整个压下去
        ve.clear(); 
        int pre=-1; 
        for(int i=0;i<=131075;i++) 
        { 
            if(mark[i]) 
            { 
                if(pre!=-1) continue; 
                pre=i; 
            } 
            else
            { 
                if(pre==-1) continue; 
                ve.push_back(make_pair(pre,i-1)); //找区间段
                pre=-1; 
            } 
        } 
        if(ve.size()==0) printf("empty set
    "); //为空
        else
        { 
            int kase=0; 
            for(int i=0;i<ve.size();i++) //输出很恶心
            { 
                int L=ve[i].first; 
                int R=ve[i].second; 
                if(kase++) printf(" "); 
                if(L%2) printf("("); 
                else printf("["); 
                printf("%d,%d",L/2,(R+1)/2); 
                if(R%2) printf(")"); 
                else printf("]"); 
            } 
            printf("
    "); 
        } 
        return 0; 
    } 
    View Code

    poj3277-City Horizon(扫描线)

    /*
    题意:给出N个矩形,都在同一水平线上,求面积并
    
    解析:裸的扫描线
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    typedef __int64 LL; 
    const int maxn=80005; 
    int N,num,A[maxn]; 
    struct node 
    { 
        int L,R,H,s; 
        node(int L=0,int R=0,int H=0,int s=0) 
        :L(L),R(R),H(H),s(s){} 
        bool operator < (const node& t) const
        { 
            return H<t.H; 
        } 
    }Nod[maxn]; 
    struct Tree 
    { 
        int le,ri,lazy; 
        int sum; 
    }tree[4*maxn]; 
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le,e.ri=ri,e.lazy=0,e.sum=0; 
        if(le==ri) return; 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        return; 
    } 
    void pushup(int id) 
    { 
        Tree& fa=tree[id]; 
        Tree& lson=tree[id*2]; 
        Tree& rson=tree[id*2+1]; 
        if(fa.lazy) fa.sum=A[fa.ri+1]-A[fa.le]; 
        else if(fa.le==fa.ri) fa.sum=0; 
        else fa.sum=lson.sum+rson.sum; 
    } 
    void update(int id,int x,int y,int c) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) 
        { 
            e.lazy+=c; 
            pushup(id); 
            return; 
        } 
        int mid=(le+ri)/2; 
        if(x<=mid) update(id*2,x,y,c); 
        if(y>mid)  update(id*2+1,x,y,c); 
        pushup(id); 
        return; 
    } 
    LL solve() 
    { 
        LL ret=0; 
        sort(Nod+1,Nod+num+1); 
        sort(A+1,A+num+1); 
        int k=1; 
        for(int i=2;i<=num;i++) if(A[i]!=A[k]) A[++k]=A[i]; 
        build_tree(1,1,k); 
        for(int i=1;i<num;i++) 
        { 
            node& t=Nod[i]; 
            int x=lower_bound(A+1,A+k+1,t.L)-A; 
            int y=lower_bound(A+1,A+k+1,t.R)-A-1; 
            update(1,x,y,t.s); 
            ret+=(LL)tree[1].sum*((LL)Nod[i+1].H-Nod[i].H); 
        } 
        return ret; 
    } 
    int main() 
    { 
        while(scanf("%d",&N)!=EOF) 
        { 
            num=0; 
            int a,b,h; 
            for(int i=1;i<=N;i++) 
            { 
                scanf("%d%d%d",&a,&b,&h); 
                Nod[++num]=node(a,b,0,1); 
                A[num]=a; 
                Nod[++num]=node(a,b,h,-1); 
                A[num]=b; 
            } 
            LL ans=solve(); 
            printf("%I64d
    ",ans); 
        } 
        return 0; 
    } 
    View Code

    poj3368-Frequent values(线段树区间合并)

    /*
    题意:给出一组非递减的数,每次查询一段区间内出现次数最多的数的个数
    
    解析:因为是非递减的,而且也不能更改,所以相同的数是连在一起的,
    考虑用线段树区间合并记录连续的最大长度。具体细节见代码。
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
    typedef __int64 LL; 
    const int maxn=100005; 
    #define fa tree[id] 
    #define lson tree[id*2] 
    #define rson tree[id*2+1] 
    int N,Q; 
    struct Tree 
    { 
        int le,ri,len; 
        int ll,rl,ml; //左边连续长度,右边连续长度,最大连续长度
        int lv,rv; //左端点值,右端点值
    }tree[4*maxn]; 
    void pushup(int id) 
    { 
        fa.ll=lson.ll; 
        if(fa.ll==lson.len&&lson.rv==rson.lv) fa.ll+=rson.ll; //延伸到右边去
        fa.rl=rson.rl; 
        if(fa.rl==rson.len&&lson.rv==rson.lv) fa.rl+=lson.rl; //延伸到左边去
        fa.ml=max(lson.ml,rson.ml); 
        if(lson.rv==rson.lv) fa.ml=max(fa.ml,lson.rl+rson.ll); //取最大值
        fa.lv=lson.lv; //左右端点的值
        fa.rv=rson.rv; 
    } 
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le, e.ri=ri, e.len=ri-le+1; 
        if(le==ri) 
        { 
            scanf("%d",&e.lv); 
            e.rv=e.lv; 
            e.ll=e.rl=e.ml=1; //叶子节点为1
            return; 
        } 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        pushup(id); 
        return; 
    } 
    int query(int id,int x,int y) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) return e.ml; 
        int mid=(le+ri)/2; 
        int ret=0; 
        if(x<=mid) ret=max(ret,query(id*2,x,y)); //左边
        if(y>mid)  ret=max(ret,query(id*2+1,x,y)); //右边
        if(x<=mid&&y>mid) 
        { 
            if(lson.rv==rson.lv) 
                ret=max(ret,min(lson.rl,mid-x+1)+min(rson.ll,y-mid)); //中间 
        } 
        return ret; 
    } 
    int main() 
    { 
        while(true) 
        { 
            scanf("%d",&N); 
            if(!N) break; 
            scanf("%d",&Q); 
            build_tree(1,1,N); 
            int x,y; 
            for(int i=1;i<=Q;i++) 
            { 
                scanf("%d%d",&x,&y); 
                printf("%d
    ",query(1,x,y)); 
            } 
        } 
        return 0; 
    }
    View Code

    zoj1610-Count the Colors(线段树区间覆盖)

    /*
    题意:给区间染色,最后求每种可见的颜色有多少段
    
    解析:区间覆盖问题,最后整个压下去,统计一下个数即可。
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    const int INF=1e9+7; 
    const double eps=1e-7; 
      
    const int maxn=8005; 
    struct Tree 
    { 
        int le,ri,lazy; 
    }tree[4*maxn]; 
    int N; 
    int color[maxn],mark[maxn]; //mark标记颜色,color记录个数
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le,e.ri=ri,e.lazy=-1; 
        if(le==ri) return; 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        return; 
    } 
    void pushdown(int id) 
    { 
        Tree& fa=tree[id]; 
        Tree& lson=tree[id*2]; 
        Tree& rson=tree[id*2+1]; 
        if(fa.lazy!=-1) 
        { 
            lson.lazy=rson.lazy=fa.lazy; 
            fa.lazy=-1; 
        } 
    } 
    void update(int id,int x,int y,int c) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) 
        { 
            e.lazy=c; 
            if(le==ri) mark[le]=c; //叶子节点
            return; 
        } 
        pushdown(id); 
        int mid=(le+ri)/2; 
        if(x<=mid) update(id*2,x,y,c); 
        if(y>mid)  update(id*2+1,x,y,c); 
        return; 
    } 
    void query(int id) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri,lazy=e.lazy; 
        if(le==ri) 
        { 
            mark[le]=lazy; //一直到叶子节点
            return; 
        } 
        pushdown(id); 
        query(id*2); 
        query(id*2+1); 
        return; 
    } 
    int main() 
    { 
        while(scanf("%d",&N)!=EOF) 
        { 
            build_tree(1,1,8000); 
            int x,y,c; 
            memset(mark,-1,sizeof(mark)); 
            for(int i=1;i<=N;i++) 
            { 
                scanf("%d%d%d",&x,&y,&c); 
                update(1,x+1,y,c); 
            } 
            query(1); 
            memset(color,0,sizeof(color)); 
            for(int i=1;i<=8000;i++) //统计个数
                if(mark[i]!=mark[i-1]) color[mark[i]]++; 
            for(int i=0;i<=8000;i++) //不为0可见
                if(color[i]) printf("%d %d
    ",i,color[i]); 
            printf("
    "); 
        } 
        return 0; 
    } 
    View Code

    zoj2706-Thermal Death of the Universe(线段树成段更新)

    /*
    题意:更新一段区间,把这段区间的数全部置为其平均数
    如果这段区间的和小于等于总和则向上取整,否则向下取整
    
    解析:线段树成段更新,注意一下题目的要求即可。
    */
    #include<cstdio> 
    #include<cstring> 
    #include<string> 
    #include<cmath> 
    #include<iostream> 
    #include<algorithm> 
    #include<vector> 
    #include<set> 
    #include<map> 
    #include<stack> 
    #include<queue> 
    #include<sstream> 
    #include<utility> 
    #include<iterator> 
    using namespace std; 
    typedef long long LL; 
    const LL INF=1e15+7; 
    const double eps=1e-7; 
    #define fa tree[id] 
    #define lson tree[id*2] 
    #define rson tree[id*2+1] 
    const int maxn=30005; 
    struct Tree 
    { 
        int le,ri; 
        LL sum,d; 
        void init(){ sum=d*(ri-le+1); } 
    }tree[4*maxn]; 
    int N,M; 
    LL mark[maxn]; 
    void pushup(int id) 
    { 
        fa.sum=lson.sum+rson.sum; 
    } 
    void build_tree(int id,int le,int ri) 
    { 
        Tree& e=tree[id]; 
        e.le=le,e.ri=ri,e.d=-INF; 
        if(le==ri) 
        { 
            scanf("%lld",&e.sum); 
            e.d=e.sum; 
            return; 
        } 
        int mid=(le+ri)/2; 
        build_tree(id*2,le,mid); 
        build_tree(id*2+1,mid+1,ri); 
        pushup(id); 
        return; 
    } 
    void pushdown(int id) 
    { 
        if(fa.d!=-INF) 
        { 
            lson.d=rson.d=fa.d; 
            lson.init(); rson.init(); 
            fa.d=-INF; 
        } 
    } 
    void update(int id,int x,int y,LL c) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) 
        { 
            e.d=c; 
            e.init(); 
            return; 
        } 
        pushdown(id); 
        int mid=(le+ri)/2; 
        if(x<=mid) update(id*2,x,y,c); 
        if(y>mid) update(id*2+1,x,y,c); 
        pushup(id); 
        return; 
    } 
    LL query(int id,int x,int y) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(x<=le&&ri<=y) return e.sum; 
        pushdown(id); 
        int mid=(le+ri)/2; 
        LL ret=0; 
        if(x<=mid) ret+=query(id*2,x,y); 
        if(y>mid)  ret+=query(id*2+1,x,y); 
        pushup(id); 
        return ret; 
    } 
    void GetMark(int id) 
    { 
        Tree& e=tree[id]; 
        int le=e.le,ri=e.ri; 
        if(le==ri){ mark[le]=e.sum; return; } 
        pushdown(id); 
        GetMark(id*2); 
        GetMark(id*2+1); 
        return; 
    } 
    int main() 
    { 
        while(scanf("%d%d",&N,&M)!=EOF) 
        { 
            build_tree(1,1,N); 
            LL org=tree[1].sum; 
            int x,y; 
            for(int k=1;k<=M;k++) 
            { 
                scanf("%d%d",&x,&y); 
                LL S=query(1,x,y); 
                LL L=y-x+1; 
                if(tree[1].sum<=org) 
                { 
                    if(S<0) update(1,x,y,-(-S/L)); 
                    else  update(1,x,y,(S+L-1)/L); 
                } 
                else
                { 
                    if(S<0) update(1,x,y,-((-S+L-1)/L)); 
                    else update(1,x,y,S/L); 
                } 
            } 
            GetMark(1); 
            int kase=0; 
            for(int i=1;i<=N;i++) 
            { 
                if(kase++) printf(" "); 
                printf("%lld",mark[i]); 
            } 
            printf("
    
    "); 
        } 
        return 0; 
    } 
    View Code
  • 相关阅读:
    Elasticsearch Network Settings
    Spring Application Event Example
    hibernate persist update 方法没有正常工作(不保存数据,不更新数据)
    快速自检电脑是否被黑客入侵过(Linux版)
    快速自检电脑是否被黑客入侵过(Windows版)
    WEB中的敏感文件泄漏
    Nginx日志分析
    关系型数据库设计小结
    软件开发的一些"心法"
    关于DNS,你应该知道这些
  • 原文地址:https://www.cnblogs.com/wust-ouyangli/p/5682527.html
Copyright © 2011-2022 走看看