• bzoj3747: [POI2015]Kinoman


    哇被靖靖D飞啊

    这题做法很是玄学,感觉最近这段时间的确是比较颓,一点写大数据结构的欲望都没有。

    首先先用一个链表存储同一部电影的出现时间。

    然后求前缀和。

    枚举左端点往右延伸,电影的出现次数也减少,判断一下加减的情况即可。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    
    struct trnode
    {
        int l,r,lc,rc;LL c,lazy;
    }tr[2100000];int trlen;
    void bt(int l,int r)
    {
        trlen++;int now=trlen;
        tr[now].l=l;tr[now].r=r;
        tr[now].lc=tr[now].rc=-1;
        tr[now].c=0;tr[now].lazy=0;
        if(l<r)
        {
            int mid=(l+r)/2;
            tr[now].lc=trlen+1;bt(l,mid);
            tr[now].rc=trlen+1;bt(mid+1,r);
            tr[now].c=max(tr[tr[now].lc].c,tr[tr[now].rc].c);
        }
    }
    void change(int now,int l,int r,LL k)
    {
        if(l>r)return ;
        if(tr[now].l==l&&tr[now].r==r)
        {
            tr[now].c+=k;
            tr[now].lazy+=k;
            return ;
        }
        
        int lc=tr[now].lc,rc=tr[now].rc;
        int mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy!=0)
        {
            tr[lc].c+=tr[now].lazy;tr[lc].lazy+=tr[now].lazy;
            tr[rc].c+=tr[now].lazy;tr[rc].lazy+=tr[now].lazy;
            tr[now].lazy=0;
        }
        
        if(r<=mid)change(lc,l,r,k);
        else if(mid+1<=l)change(rc,l,r,k);
        else change(lc,l,mid,k),change(rc,mid+1,r,k);
        
        tr[now].c=max(tr[lc].c,tr[rc].c);
    }
    LL findmax(int now,int l,int r)
    {
        if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
        
        int lc=tr[now].lc,rc=tr[now].rc;
        int mid=(tr[now].l+tr[now].r)/2;
        if(tr[now].lazy!=0)
        {
            tr[lc].c+=tr[now].lazy;tr[lc].lazy+=tr[now].lazy;
            tr[rc].c+=tr[now].lazy;tr[rc].lazy+=tr[now].lazy;
            tr[now].lazy=0;
        }
        if(r<=mid)return findmax(lc,l,r);
        else if(mid+1<=l)return findmax(rc,l,r);
        else return max(findmax(lc,l,mid),findmax(rc,mid+1,r));
    }
    int f[1100000];
    int num[1100000],next[1100000],first[1100000];
    LL s[1100000],w[1100000];
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&f[i]);
        for(int i=1;i<=m;i++)scanf("%d",&w[i]);
        memset(first,0,sizeof(first));
        for(int i=n;i>=1;i--)
        {
            next[i]=first[f[i]];
            first[f[i]]=i;
        }
        for(int i=1;i<=n;i++)
        {
            s[i]=s[i-1];
            if(num[f[i]]==0)s[i]+=w[f[i]];
            if(num[f[i]]==1)s[i]-=w[f[i]];
            num[f[i]]++;
        }
        trlen=0;bt(1,n);
        for(int i=1;i<=n;i++)change(1,i,i,s[i]);
        
        LL ans=0;
        for(int i=1;i<=n;i++)
        {
            ans=max(ans,findmax(1,i,n));
            if(next[i]!=0)
            {
                change(1,i+1,next[i]-1,-w[f[i]]);
                if(next[next[i]]!=0)
                    change(1,next[i],next[next[i]]-1,w[f[i]]);
                else
                    change(1,next[i],n,w[f[i]]);
            }
            else change(1,i+1,n,-w[f[i]]);
        }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Celery最佳实践(转)
    我希望知道的关于Django的11件事(转)
    Celery和Rabbitmq自学
    我眼中的各种编程语言(转)
    linux 的nohup & 和daemon 总结(转)
    模糊测试之AVI文件分析
    微信Netting-QRLJacking分析利用-扫我二维码获取你的账号权限
    一个Unix内核级别漏洞(一)
    一次对SNMP服务的渗透测试
    定位日站大法之-社会工程学
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8697372.html
Copyright © 2020-2023  润新知