hdu5861 Road,线段树,然后扫描

佣神给的思路

线段树预处理每一个road的起始和结束时间
然后排序按天数扫描,每天看有没有需要增加新路,看有没有需要关闭路
因为是排好序的,所以不会重复扫

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=600100;
int n,ans,m,a[N];
struct node {
    int l,r,id;
    node () { }
    node(int x,int y,int z){l=x;r=y;id=z;}
}b[N],c[N];
inline bool cmp1(node a,node b){return a.l<b.l;}
inline bool cmp2(node a,node b){return a.r<b.r;}

struct linetree{
    #define lc  (t<<1)
    #define rc  (t<<1^1)
    #define mid (l[t]+r[t]>>1)
    int l[N],r[N],ma[N],mi[N],M,ta[N],ti[N];
    inline void build(int n){
        M=1; while(M<n)M<<=1; M--;
        memset(ma, 0 ,sizeof(ma));
        memset(mi,INF,sizeof(mi));
        memset(ta, 0 ,sizeof(ta));
        memset(ti,INF,sizeof(ti));
        for (int i=1+M;i<=M*2+1;i++)l[i]=r[i]= i-M ;
        for (int t=M;t>=1;t--)l[t]=l[lc],r[t]=r[rc];
    }
    inline void down(int t){
        if (t>M)return ;//leaf node
        ma[lc]=max(ma[lc],ta[t]);
        ma[rc]=max(ma[rc],ta[t]);
        ta[lc]=max(ta[lc],ta[t]);
        ta[rc]=max(ta[rc],ta[t]);
        ta[t] = 0;

        mi[lc]=min(mi[lc],ti[t]);
        mi[rc]=min(mi[rc],ti[t]);
        ti[lc]=min(ti[lc],ti[t]);
        ti[rc]=min(ti[rc],ti[t]);
        ti[t] = INF;
    }
    inline void maintain(int t){
        ma[t]=max(ma[lc],ma[rc]);
        mi[t]=min(mi[lc],mi[rc]);
    }
    inline void tag(int t,int x){
        ma[t]=max(ma[t],x);
        mi[t]=min(mi[t],x);
        ta[t]=max(ta[t],x);
        ti[t]=min(ti[t],x);
    }
    void change(int t,int L,int R,int x){
        if (L<=l[t]&&r[t]<=R){tag(t,x);return;}
        down(t);
        if (L<=mid)change(lc,L,R,x);
        if (mid< R)change(rc,L,R,x);
        maintain(t);
    }
    void query(int t){
        if (t>M){//leaf node
            b[t-M]=c[t-M]=node(mi[t],ma[t],t-M);
            return ;
        }
        down(t);
        query(lc);
        query(rc);
        maintain(t);
    }
}T;

int main(){
    //freopen("fuck.in","r",stdin);
    int l,r;
    while (scanf("%d%d",&n,&m)==2){
        for (int i=1;i<n;i++)scanf("%d",&a[i]);
        T.build(n-1) ;
        for (int i=1;i<=m;i++){
            scanf("%d%d",&l,&r);
            if(l>=r) swap(l,r) ;
            T.change(1,l,r-1,i);
        }
        T.query(1);
        sort(b+1, b+n, cmp1);
        sort(c+1, c+n, cmp2);
        int x=1, y=1, ans=0 ;
        for (int i=1;i<=m;i++){
            for (; x<n &&b[x].l<=i;x++)
                if(b[x].l<=b[x].r)ans+=a[b[x].id];

            for (; y<n &&c[y].r< i;y++)
                if(c[y].l<=c[y].r)ans-=a[c[y].id];
            printf("%d\n" , ans);
        }
    }
    return 0;
}

多校训练结束啦,闷声滚大粗了
我好菜啊

其实,,因为是单点查询,而且所有点顺序查一次就行了
所以,,不需要tag,不需要maintain

新姿势

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=600100;
int n,ans,m,a[N];
struct node {
    int l,r,id;
    node () { }
    node(int x,int y,int z){l=x;r=y;id=z;}
}b[N],c[N];
inline bool cmp1(node a,node b){return a.l<b.l;}
inline bool cmp2(node a,node b){return a.r<b.r;}

struct linetree{
    #define lc  (t<<1)
    #define rc  (t<<1^1)
    #define mid (l[t]+r[t]>>1)
    int l[N],r[N],ma[N],mi[N],M;
    inline void build(int n){
        M=1; while(M<n)M<<=1; M--;
        memset(ma, 0 ,sizeof(ma));
        memset(mi,INF,sizeof(mi));
        for (int i=1+M;i<=M*2+1;i++)l[i]=r[i]= i-M ;
        for (int t=M;t>=1;t--)l[t]=l[lc],r[t]=r[rc];
    }
    inline void down(int t){
        if (t>M)return ;//leaf node
        ma[lc]=max(ma[lc],ma[t]);
        ma[rc]=max(ma[rc],ma[t]);
        mi[lc]=min(mi[lc],mi[t]);
        mi[rc]=min(mi[rc],mi[t]);
    }
    inline void tag(int t,int x){
        ma[t]=max(ma[t],x);
        mi[t]=min(mi[t],x);
    }
    void change(int t,int L,int R,int x){
        if (L<=l[t]&&r[t]<=R){tag(t,x);return;}//in
        down(t);
        if (L<=mid)change(lc,L,R,x);
        if (mid< R)change(rc,L,R,x);
    }
    void query(int t){
        if (t>M){//leaf node
            b[t-M]=c[t-M]=node(mi[t],ma[t],t-M);
            return ;
        }
        down(t);
        query(lc);
        query(rc);
    }
}T;

int main(){
    //freopen("fuck.in","r",stdin);
    int l,r;
    while (scanf("%d%d",&n,&m)==2){
        for (int i=1;i<n;i++)scanf("%d",&a[i]);
        T.build(n-1) ;
        for (int i=1;i<=m;i++){
            scanf("%d%d",&l,&r);
            if(l>=r) swap(l,r) ;
            T.change(1,l,r-1,i);
        }
        T.query(1);
        sort(b+1, b+n, cmp1);
        sort(c+1, c+n, cmp2);
        int x=1, y=1, ans=0 ;
        for (int i=1;i<=m;i++){
            for (; x<n &&b[x].l<=i;x++)
                if(b[x].l<=b[x].r)ans+=a[b[x].id];
            for (; y<n &&c[y].r< i;y++)
                if(c[y].l<=c[y].r)ans-=a[c[y].id];
            printf("%d\n" , ans);
        }
    }
    return 0;
}
posted @ 2016-08-18 20:58  伟大的蚊子  阅读(63)  评论(0编辑  收藏  举报