• 2020 hdu多校赛 第八场 1002 Breaking Down News


    题意:

    给你一个由 -1 1 0组成的数列(n<=1e6),要求你把这个数列分为若干子串,L<=每一段长度<=R,如果这一段内的和大于 0 则这一段的价值为 1 ,小于 0 为  -1 ,等于 0 为 0。

    问你这些子串的和最大是多少。

    首先,我们考虑如果没有L  R限制该如何处理:

    设 sum[i] 为1~i 的前缀和

    如果 sum[ x ]<sum[ i ] ( x < i ),则 x+1~i 的区间和小于 0

    如果 sum[ x ]=sum[ i ] ,则x+1~i 的区间和等于0

    如果 sum[ x ]>sum[ i ],则x+1~i 的区间和大于0

    设F[i]为 1~i 的最优解

    我们就可以用sum[i]建权值线段树,表示前缀和为某值时F[i]最大为多少。

    每次在-n~sum[i]-1 sum[i] sum[i]+1~n 里面去找最大值然后转移即可。


    那么现在有了L R的限制我们应该怎么办呢?

    因为 i 比 i+1 的合法转移区间只会少一个左端点多一个右端点。我们直接在线段树上修改即可。

    而维护某个前缀和值的最大F[i]可以用可删除堆来实现。


    不过,由于这一道题 ai只有 1 -1 0,相邻两个位置的前缀和最大也只差 1 ,我们也可以用三个堆来表示比sum[i] 小、等、大的解,每次把其中的某个不合法或新合法元素插入删除即可。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<cstdlib>
      7 #include<queue>
      8 #include<map>
      9 #define N 1000005
     10 using namespace std;
     11 char xch,xB[1<<15],*xS=xB,*xTT=xB;
     12 #define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
     13 inline int read()
     14 {
     15     int x=0,f=1;char ch=getc();
     16     while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
     17     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
     18     return x*f;
     19 }
     20 map<int,int> ma;
     21 int T,n,L,R;
     22 int A[N];
     23 int sum[N];
     24 int zz,B[N];
     25 struct no{
     26     int left,right,mid;
     27     int mx;
     28 }node[N*4];
     29 priority_queue<int> q1[N],q2[N];
     30 void build(int left,int right,int x)
     31 {
     32     node[x].left=left;
     33     node[x].right=right;
     34     node[x].mx=-1e7;
     35     if(left==right)
     36     {
     37         return;
     38     }
     39     int mid=(left+right)>>1;
     40     node[x].mid=mid;
     41     build(left,mid,x<<1);
     42     build(mid+1,right,x<<1|1);
     43 }
     44 int F[N];
     45 int get(int left,int right,int x)
     46 {
     47     if(left>right)return -1e7;
     48     if(left==node[x].left&&right==node[x].right)
     49     {
     50         return node[x].mx;
     51     }
     52     int mid=node[x].mid;
     53     if(left>mid) return get(left,right,x<<1|1);
     54     else if(right<=mid)return get(left,right,x<<1);
     55     else return max(get(left,mid,x<<1),get(mid+1,right,x<<1|1));
     56 }
     57 void ch(int to,int x,int da)
     58 {
     59     if(node[x].left==node[x].right)
     60     {
     61         node[x].mx=da;
     62         return;
     63     }
     64     int mid=node[x].mid;
     65     if(to>mid) ch(to,x<<1|1,da);
     66     else ch(to,x<<1,da);
     67     node[x].mx=max(node[x<<1].mx,node[x<<1|1].mx);
     68 }
     69 int main()
     70 {
     71     T=read();
     72     while(T--)
     73     {
     74         n=read();
     75         L=read();
     76         R=read();
     77         ma.clear();
     78         zz=0;
     79         for(int i=1;i<=n;i++)
     80         {
     81             A[i]=read();
     82             sum[i]=sum[i-1]+A[i];
     83             if(!ma[sum[i]])
     84             {
     85                 zz++;
     86                 B[zz]=sum[i];
     87                 ma[sum[i]]=1;
     88             }
     89             F[i]=0;
     90         }
     91         if(!ma[0])
     92         {
     93             zz++;
     94             B[zz]=0;
     95             ma[0]=1;
     96         } 
     97         sort(B+1,B+zz+1);
     98         for(int i=1;i<=zz;i++)
     99         {
    100             ma[B[i]]=i;
    101             while(!q1[i].empty()) q1[i].pop();
    102             while(!q2[i].empty()) q2[i].pop();
    103         }
    104         build(1,zz,1);
    105         q1[ma[0]].push(0);
    106         ch(ma[0],1,0);
    107         for(int i=1;i<=L;i++) F[i]=-1e7;
    108         for(register int i=L;i<=n;++i)
    109         {
    110             F[i]=max(max(get(1,ma[sum[i]]-1,1)+1,get(ma[sum[i]],ma[sum[i]],1)),get(ma[sum[i]]+1,zz,1)-1);
    111             if(F[i]>n||F[i]<-n) F[i]=-1e7;
    112             if(i-L+1>=0&&F[i-L+1]!=-1e7)
    113             {
    114                 int tmp=ma[sum[i-L+1]];
    115                 
    116                 q1[tmp].push(F[i-L+1]);
    117                 
    118                 while(!q1[tmp].empty()&&!q2[tmp].empty()&&q1[tmp].top()==q2[tmp].top()) q1[tmp].pop(),q2[tmp].pop();
    119                 ch(tmp,1,q1[tmp].top());
    120             }
    121             if(i-R>=0&&F[i-R]!=-1e7)
    122             {
    123                 int tmp=ma[sum[i-R]];
    124                 q2[tmp].push(F[i-R]);
    125                 
    126                 while(!q1[tmp].empty()&&!q2[tmp].empty()&&q1[tmp].top()==q2[tmp].top()) q1[tmp].pop(),q2[tmp].pop();
    127                 if(q1[tmp].empty()) ch(tmp,1,-1e7);
    128                 else ch(tmp,1,q1[tmp].top());
    129             }
    130         }
    131         printf("%d
    ",F[n]);
    132     }
    133     return 0;
    134 }
    135 /*
    136 1
    137 5 1 1
    138 1 -1 0 -1 1
    139 */
    View Code
  • 相关阅读:
    Hibernate实体对象三种状态
    tar命令: 对某目录文件打tar包时,排除指定的目录或文件
    开发项目时,提示 找不到类的解决方法,以及如何设置编译源目录
    当html中存在url中如: onclick="toView('参数1')", 参数1是特别字符,如&asop;&quot;' "等时,浏览器解析时会报错。解决方法如文中描述
    oracle表分区心得
    启动系统相关服务笔记整理
    使用PSD设计网页页面
    JAR、WAR、EAR 区别
    设置 MyEclipse 默认打开文件方式
    前端性能优化
  • 原文地址:https://www.cnblogs.com/liutianrui/p/13498801.html
Copyright © 2020-2023  润新知