zoukankan      html  css  js  c++  java
  • CF1108E2 Array and Segments (Hard version)

    线段树

    对于$Easy$ $version$可以枚举极大值和极小值的位置,然后判断即可

    但对于$Hard$ $version$明显暴力同时枚举极大值和极小值会超时

    那么,考虑只枚举极小值

    对于数轴上每一个点,记录开始和结束于这个点的区间

    那么从1枚举到i时可以处理出当包含i点所有区间

    所以用线段树维护修改这些区间,进行判断总区间的极差

    记录最大值即可

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=1e5+100;
    int n,m,a[MAXN],l[310],r[310];
    int ans,wh;
    vector <int> t,be[MAXN],ed[MAXN];
    struct node
    {
        int l,r,MAX,MIN,sum,lazy;
    }sh[MAXN*4];
    void pushup(int x)
    {
        sh[x].sum=sh[x+x].sum+sh[x+x+1].sum;
        sh[x].MAX=max(sh[x+x].MAX,sh[x+x+1].MAX);
        sh[x].MIN=min(sh[x+x].MIN,sh[x+x+1].MIN);
    }
    void pushdown(int x)
    {
        if (sh[x].lazy!=0)
        {
            sh[x+x].lazy+=sh[x].lazy;
            sh[x+x+1].lazy+=sh[x].lazy;
            sh[x+x].sum+=sh[x].lazy;
            sh[x+x].MAX+=sh[x].lazy;
            sh[x+x].MIN+=sh[x].lazy;
            sh[x+x+1].sum+=sh[x].lazy;
            sh[x+x+1].MAX+=sh[x].lazy;
            sh[x+x+1].MIN+=sh[x].lazy;
            sh[x].lazy=0;
        }
    }
    void build(int x,int ll,int rr)
    {
        sh[x].l=ll;
        sh[x].r=rr;
        if (ll==rr)
        {
            sh[x].MAX=sh[x].MIN=sh[x].sum=a[ll];
            return;
        }
        int mid;
        mid=(ll+rr)>>1;
        build(x+x,ll,mid);
        build(x+x+1,mid+1,rr);
        pushup(x);
    }
    void change(int x,int ll,int rr,int k)//区间修改
    {
        if (sh[x].l>=ll && sh[x].r<=rr)
        {
            sh[x].sum+=k;
            sh[x].MIN+=k;
            sh[x].MAX+=k;
            sh[x].lazy+=k;
            return;
        }
        pushdown(x);
        int mid;
        mid=(sh[x].l+sh[x].r)>>1;
        if (ll<=mid)
          change(x+x,ll,rr,k);
        if (rr>mid)
          change(x+x+1,ll,rr,k);
        pushup(x);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
          scanf("%d",&a[i]);
        for (int i=1;i<=m;i++)
          scanf("%d%d",&l[i],&r[i]);
        build(1,1,n);
        if (n==1)
        {
            printf("0
    0
    ");
            return 0;
        }
        for (int i=1;i<=m;i++)
        {
            be[l[i]].push_back(i);//对于结束和开始的节点记录区间
            ed[r[i]].push_back(i);
        }
        ans=sh[1].MAX-sh[1].MIN;
        wh=0;
        for (int i=1;i<=n;i++)
        {
            for (int j=0;j<(int)ed[i-1].size();j++)
            {
                int u;
                u=ed[i-1][j];
                change(1,l[u],r[u],1);//将之前修改的区间对当前无影响改回去
            }
            for (int j=0;j<(int)be[i].size();j++)
            {
                int u;
                u=be[i][j];
                change(1,l[u],r[u],-1);//将新增的区间修改
            }
            pushdown(1);
            pushup(1);
            if (sh[1].MAX-sh[1].MIN>ans)//记录当期的极差
            {
                ans=sh[1].MAX-sh[1].MIN;
                wh=i;
            }
        }
        for (int i=1;i<=m;i++)
        {
            if (l[i]<=wh && r[i]>=wh)
              t.push_back(i);
        }
        printf("%d
    %d
    ",ans,(int)t.size());
        for (int i=0;i<(int)t.size();i++)
          printf("%d ",t[i]);
        printf("
    ");
    }
  • 相关阅读:
    RabbitMQ安装(发生系统错误5。拒绝访问。发生系统错误1067。进程意外终止。)
    SQLServer执行脚本提示“系统找不到指定的文件”或“内存资源不足”
    TypeScript@HelloWorld!
    超详细Node安装教程
    进制转换
    菜鸟成长记
    ASP.NET Core中使用MialKit实现邮件发送
    VS未能正确加载 ”Microsoft.VisualStudio.Editor.Implementation.EditorPackate“包错误解决方法
    C#Winfrom Listview数据导入Excel
    安装研发服务器
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/11239020.html
Copyright © 2011-2022 走看看