zoukankan      html  css  js  c++  java
  • J. Joy of Handcraft

    每个灯泡会闪ti分钟,然后灭ti分钟。

    灯泡闪的时候亮度为bi

    最后问每分钟最亮的亮度是多少。

    首先先对灯泡排序,这样相同t值的不重复更新

    灯泡去重之后最多只有m个。

    线段树维护”时间“这个区间上的最大值。

    最多的情况下,m要被更新m/1+m/2+m/3…+m/m=mlogm

    区间个数是个调和级数

    最后乘上线段树的logm,时间复杂度为mloglogm,可以ac

    #include<bits/stdc++.h>
    #define inf 1e18
    #define ll long long 
    #define ull unsigned long long 
    #define int long long
    #define PI acos(-1.0)
    #define PII pair<int,int>
    using namespace std;
    const int N = 2e5+7 , M = N * 2;
    const int mod = 1e9+7;
    int m,p,n,las,vis[N];
    struct bumb{
        int t,x;
    }b[N];
    int cmp(bumb xx,bumb yy){
        return xx.x>yy.x;
    }
    struct node{
        int l,r;
        int v;
        int lz;
    }tr[N*4];
    void pushdown(int u,int l,int r){
        tr[l].lz = max(tr[l].lz,tr[u].lz);
        tr[r].lz = max(tr[r].lz,tr[u].lz);
        tr[l].v = max(tr[l].v,tr[u].lz);
        tr[r].v = max(tr[r].v,tr[u].lz);
        tr[u].lz = 0;
    }
    void pushdown(int u){
        pushdown(u,u<<1,u<<1|1);
    }
    void pushup(int u){
        tr[u].v = max(tr[u<<1].v,tr[u<<1|1].v);
    }
    void build(int u,int l,int r){
        tr[u]={l,r,0,0};
        if(l==r)    return ;
        int mid = l + r >>1;
        build(u<<1,l,mid);build(u<<1|1,mid+1,r);
        pushup(u);
    }
    void modify(int u,int l,int r,int k){
        if(l<=tr[u].l&&r>=tr[u].r){
            tr[u].lz = max(tr[u].lz,k);
            tr[u].v = max(tr[u].v,k);
            return ;
        }
        pushdown(u);
        int mid = tr[u].l + tr[u].r >>1;
        if(l<=mid)    modify(u<<1,l,r,k);
        if(r>mid)    modify(u<<1|1,l,r,k);
        pushup(u);
    }
    int query(int u,int l,int r){
        if(l<=tr[u].l&&r>=tr[u].r)
            return tr[u].v;
        pushdown(u);
        int ans=0;
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)        ans=max(ans,query(u<<1,l,r));
        if(r>mid)        ans=max(ans,query(u<<1|1,l,r));
        return ans;
    }
    void solve(){
        memset(vis,0,sizeof(vis));
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;++i)
            scanf("%lld%lld",&b[i].t,&b[i].x);
        sort(b+1,b+1+n,cmp);
        build(1,1,m);
        for(int i=1;i<=n;++i){
            if(vis[b[i].t]==1)    continue;
            vis[b[i].t]=1;
            int st=1,ed=b[i].t;
            while(st<=m){
                modify(1,st,min(ed,m),b[i].x);
                st=st+2*b[i].t;ed=ed+2*b[i].t;
            }
        }
        for(int i=1;i<=m;++i)
            printf(" %lld",query(1,i,i));
        printf("
    ");
    }
    signed main(){
        int t=1;
        scanf("%lld",&t);
        for(int _=1;_<=t;++_){
            printf("Case #%lld:",_);
            solve();
        }
        return 0;
    }

     线段树的做法会过于繁琐

    如果从大到小染色,那么先染色的时间点一定不会再被更优的更新

    在这里可以用并查集来维护已经染色的区间

    这样就可以快速的跳过染色过的区间

    #include<bits/stdc++.h>
    #define inf 1e18
    #define ll long long 
    #define ull unsigned long long 
    #define int long long
    #define PI acos(-1.0)
    #define PII pair<int,int>
    using namespace std;
    const int N = 2e5+7 , M = N * 2;
    const int mod = 1e9+7;
    int m,p,n,las,vis[N],ans[N],fa[N];
    struct bumb{
        int t,x;
    }b[N];
    int cmp(bumb a,bumb b){
        return a.x>b.x;
    }
    int find(int x){
        if(x == fa[x]) return x;
        return fa[x]=find(fa[x]);
    }
    void solve(){
        memset(vis,0,sizeof(vis));
        scanf("%lld%lld",&n,&m);
        for(int i=1;i<=n;++i){
            scanf("%lld%lld",&b[i].t,&b[i].x);
        }
        for(int i=1;i<=m;++i){
            ans[i] = 0;fa[i] = i;
        }
        sort(b+1,b+1+n,cmp);
        for(int i=1;i<=n;++i){
            if(vis[b[i].t]==1)    continue;
            vis[b[i].t]=1;
            
            for(int st = 1;st <= m;st=st+2*b[i].t){//区间起点 
                for(int pos = st;pos<st+b[i].t && pos<=m;pos++){//更新区间 
                    if(ans[pos]==0)    ans[pos]=b[i].x,fa[pos-1]=pos;
                    else            pos = find(pos);//直接跳到已经染色过的末尾 
                }
            }
        }
        for(int i=1;i<=m;++i)
            printf(" %lld",ans[i]);
        printf("
    ");
    }
    signed main(){
        int t=1;
        scanf("%lld",&t);
        for(int _=1;_<=t;++_){
            printf("Case #%lld:",_);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    C# lock
    read appSettings in configuration file by XElement with xmlns
    get all sites under IIS
    Cross-site scripting(XSS)
    Do not throw System.Exception, System.SystemException, System.NullReferenceException, or System.IndexOutOfRangeException intentionally from your own source code
    C++ 算法
    C++ 数据结构概念
    C++ STL 常用算术和生成算法
    C++ STL 常用拷贝和替换算法
    C++ STL 常用排序算法
  • 原文地址:https://www.cnblogs.com/PdrEam/p/14048614.html
Copyright © 2011-2022 走看看