• 19_05_01校内训练[划分]


    题意

    给出长度为n的序列,只有1,0,-1。要求将其划分为若干长度在[L,R]之间的连续序列,一个序列若和大于0,造成1的贡献;若小于0,造成-1的贡献;否则没有贡献。求最大的贡献。

    时间复杂度要求nlogn。


    思考

    线段树维护即可。以造成1的贡献为例。设当前前缀和为sumi,则需要在[max(0,i-R),i-L]中找到最大的f。以sum为下标,建立权值线段树,在叶子节点处维护单调队列即可。

    需要注意的是,在上述范围中的f可能是不合法的(如i=4,l=r=3时,f1是无意义的),要将其赋值为-inf。


    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1E6+5;
      4 const int inf=10000001;
      5 int n,a[maxn],sum[maxn],x,f[maxn],L,R,t[maxn*4],ans[maxn*4],head[maxn*4],where[maxn];
      6 int base=INT_MAX;
      7 bool yes[maxn];
      8 struct pt
      9 {
     10     int num,x;
     11 };
     12 vector<pt>q[maxn*4];
     13 void update(int num)
     14 {
     15     ans[num]=max(ans[num<<1],ans[num<<1|1]);
     16 }
     17 void add(int l,int r,int pos,int x,int y,int num)
     18 {
     19     if(l==r)
     20     {
     21         while(head[num]<=int(q[num].size()-1)&&q[num][q[num].size()-1].x<=x)
     22         {
     23             yes[q[num][q[num].size()-1].num]=1;
     24             q[num].pop_back();
     25         }
     26         q[num].push_back((pt){y,x});
     27         ans[num]=q[num][head[num]].x;
     28         return;
     29     }
     30     int mid=(l+r)>>1;
     31     if(pos<=mid)add(l,mid,pos,x,y,num<<1);
     32     else add(mid+1,r,pos,x,y,num<<1|1);
     33     update(num);
     34 }
     35 void remove(int l,int r,int pos,int y,int num)
     36 {
     37     if(l==r)
     38     {
     39 //        cout<<head[num]<<" "<<q[num].size()<<endl
     40         if(head[num]>int(q[num].size())-1)return;
     41         if(q[num][head[num]].num!=y)return;
     42         if(head[num]<=int(q[num].size())-1&&!yes[q[num][head[num]].num])
     43         {
     44             yes[q[num][head[num]].num]=1;
     45             ++head[num];
     46         }
     47         if(head[num]<=int(q[num].size())-1)ans[num]=q[num][head[num]].x;
     48         else ans[num]=-inf;
     49         return;
     50     }
     51     int mid=(l+r)>>1;
     52     if(pos<=mid)remove(l,mid,pos,y,num<<1);
     53     else remove(mid+1,r,pos,y,num<<1|1);
     54     update(num);
     55 }
     56 int ask(int L,int R,int l,int r,int num)
     57 {
     58     if(L<=l&&r<=R)return ans[num];
     59     int mid=(l+r)>>1;
     60     if(R<=mid)return ask(L,R,l,mid,num<<1);
     61     else if(mid<L)return ask(L,R,mid+1,r,num<<1|1);
     62     else return max(ask(L,R,l,mid,num<<1),ask(L,R,mid+1,r,num<<1|1));
     63 }
     64 int main()
     65 {
     66     ios::sync_with_stdio(false);
     67     cin>>n>>L>>R;
     68     for(int i=1;i<=n;++i)
     69         add(1,n,i,-inf,0,1);
     70     for(int i=1;i<=n;++i)
     71     {
     72         cin>>x;
     73         sum[i]=sum[i-1]+x;
     74         base=min(base,sum[i]);
     75     }
     76     for(int i=1;i<=n;++i)
     77         f[i]=-inf;
     78     base=-base+1;
     79     for(int i=L;i<=R;++i)
     80     {
     81         if(sum[i]>0)f[i]=1;
     82         else if(sum[i]<0)f[i]=-1;
     83         else f[i]=0;
     84     }
     85     for(int i=L;i<=n;++i)
     86     {
     87         int p;
     88         if(sum[i]+base-1>=1)
     89         {
     90             p=ask(1,sum[i]+base-1,1,n,1);
     91             f[i]=max(f[i],p+1);
     92         }
     93         if(sum[i]+base+1<=n)
     94         {
     95             p=ask(sum[i]+base+1,n,1,n,1);
     96             f[i]=max(f[i],p-1);
     97         }
     98         p=ask(sum[i]+base,sum[i]+base,1,n,1);
     99         f[i]=max(f[i],p);
    100         if(i-L+1>=L)
    101             add(1,n,sum[i-L+1]+base,f[i-L+1],i-L+1,1);
    102         if(i-R>=L)
    103             remove(1,n,sum[i-R]+base,i-R,1);
    104     }
    105     if(f[n]<=-5000000)cout<<"IMPOSSIBLE"<<endl;
    106     else cout<<f[n]<<endl;
    107     return 0;
    108 }
    View Code
  • 相关阅读:
    树莓派安装parrot linux记录
    Arch linux(UEFI+GPT)安装及后续优化教程
    VS部分安全函数用法
    C语言博客作业06--结构体&文件
    C语言博客作业05--指针
    C语言博客作业04--数组
    C语言博客作业03--函数
    C语言博客作业02--循环结构
    DS博客作业08--课程总结
    DS博客作业07--查找
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/10800026.html
Copyright © 2020-2023  润新知