zoukankan      html  css  js  c++  java
  • B

    链接:

    https://vjudge.net/contest/202699#problem/B

    题意:

    给出一个序列,要支持区间加和操作

    求其中最长的区间,该区间内的元素满足(ai<ai+1<。。。ak>ak+1>。。>aj-1>aj)

    要支持区间加值

    题解:

    是一个很经典的差分

    对于相邻两项要判断大小只需看差分数组即可

    而对于区间修改,只需对差分数组进行单点修改即可

    接下来问题可以转化为,给出一个只有-1,0,1的数列,求最长的11111...-1-1-1-1...

    可以考虑用线段树进行维护5个值

    1.left1数组 表示从左端点开始都为-1

    2.leftt数组 表示从左端点开始先为1再为-1

    3.right1数组 表示从右端点之前到右端点都为1

    4.rightt数组  表示从右端点之前到右端点 先为1后为-1

    5.maxn数组 维护该节点中的最长区间

    为了处理的方便,其中2包含1,4包含3

    另外,只有当值的正负发生变化时才调用change函数,否则会超时

    #其中对right和left的更新有一些复杂,具体见代码

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define max1 3000000
    long long a[max1],maxn[max1],right1[max1],left1[max1],rightt[max1],leftt[max1],sum[max1];
    struct re{long long h,t;}p[max1];
    void js(long long x)
    {
        long long len1=p[x*2].t-p[x*2].h+1,len2=p[x*2+1].t-p[x*2+1].h+1;
        maxn[x]=max(max(maxn[x*2],maxn[x*2+1]),max(rightt[x*2]+left1[x*2+1],right1[x*2]+leftt[x*2+1]));
        if (right1[x*2+1]==len2) right1[x]=right1[x*2+1]+right1[x*2]; else right1[x]=right1[x*2+1];
        if (rightt[x*2+1]==len2)
        { 
          rightt[x]=rightt[x*2+1]+right1[x*2];
          if (sum[p[x*2+1].h]<0) rightt[x]=max(rightt[x],rightt[x*2+1]+rightt[x*2]);
      }  
      else rightt[x]=rightt[x*2+1];
      if (left1[x*2]==len1) left1[x]=left1[x*2+1]+left1[x*2]; else left1[x]=left1[x*2];
        if (leftt[x*2]==len1)
        {
            leftt[x]=leftt[x*2]+left1[x*2+1];
            if (sum[p[x*2].t]>0) leftt[x]=max(leftt[x],leftt[x*2+1]+leftt[x*2]);
      }
      else leftt[x]=leftt[x*2];
    };
    void build(long long x,long long h,long long t)
    {
        p[x].h=h; p[x].t=t;
        if (h==t) 
        {
            long long i=p[x].h;
        if (sum[i]==0) maxn[x]=left1[x]=right1[x]=rightt[x]=leftt[x]=0;
        if (sum[i]>0) maxn[x]=leftt[x]=rightt[x]=right1[x]=1,left1[x]=0;
        if (sum[i]<0) maxn[x]=left1[x]=leftt[x]=rightt[x]=1,right1[x]=0; 
          return;
      }
        long long mid=(h+t)/2;
        build(x*2,h,mid); 
        build(x*2+1,mid+1,t); 
        js(x);
    };
    void change(long long x,long long pos)
    { 
      if (p[x].h==p[x].t)
      { 
        long long i=p[x].h;
        if (sum[i]==0) maxn[x]=left1[x]=leftt[x]=right1[x]=rightt[x]=0;
        if (sum[i]>0) maxn[x]=leftt[x]=rightt[x]=right1[x]=1,left1[x]=0;
        if (sum[i]<0) maxn[x]=left1[x]=leftt[x]=rightt[x]=1,right1[x]=0; 
        return;
      }
        long long mid=(p[x].h+p[x].t)/2; 
      if (pos<=mid) change(x*2,pos); else change(x*2+1,pos);
      js(x);
    };
    int main()
    {
        std::ios::sync_with_stdio(false);
        long long n,m,c,d,e;
        cin>>n;
        for (long long i=1;i<=n;i++) cin>>a[i];
        for (long long i=2;i<=n;i++) sum[i]=a[i]-a[i-1];
        build(1,1,n);
        cin>>m;
        bool tt;
        for (long long i=1;i<=m;i++)
        {
            cin>>c>>d>>e;
            if (c!=1) 
            { 
              tt=false;
              if (sum[c]==0) tt=true;
                if ((sum[c]>0 && sum[c]+e<=0)||(sum[c]<0 && sum[c]+e>=0)) 
                  tt=true;
                sum[c]+=e;
                if (tt) change(1,c);
          }
          tt=false;
          if (sum[d+1]==0) tt=true;
          if ((sum[d+1]>0 && sum[d+1]-e<=0)||(sum[d+1]<0 && sum[d+1]-e>=0)) 
                tt=true;
            sum[d+1]-=e;
            if (tt) change(1,d+1);
            cout<<maxn[1]+1<<endl;
        }
        return(0);
    }
  • 相关阅读:
    个人第三次作业——原型设计
    《构建之法》团队作业第一次
    vsCode如何将结果输入到调试控制台
    Beta-冲刺第三天
    Beta版本(有更改)
    Beta冲刺-第二天
    Beta冲刺—第一天
    个人作业-测试
    团队项目—系统设计
    团队项目-需求分析
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/8053711.html
Copyright © 2011-2022 走看看