• 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
    " , 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
    " , ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    伙伴宿舍管理系统(源码下载)
    清空SQL数据库日志
    indexOf(String.indexOf 方法)
    C#实现QQ助手(登录QQ,发消息,查任意QQ资料)附源码下载
    C#cookie自动获取工具发布
    winform中怎么动态修改窗体的大小
    IIS Rewrite 下载与配置
    HTML代码转JS|C#字符串工具(附源代码)
    FTPHelper-FTP帮助类,常用操作方法
    c# 怎么动态修改webservice的地址和端口 动态修改配置文
  • 原文地址:https://www.cnblogs.com/cww97/p/12349385.html
Copyright © 2020-2023  润新知