• CF992E Nastya and King-Shamans(线段树二分+思维)


    这是一道卡常好题

    从160s卡到36s
    qwq

    由于题目设计到原数组的单点修改,那么就对应着前缀和数组上的区间加。

    很显然能想到用线段树来维护这么个东西。

    那么该如果求题目要求的位置呢

    我们来看这个题的式子,他要求$$a_i = s_{i-1}$$

    我们稍微变形一下$$s_i-s_{i-1}=s_{i-1}$$

    [s_i = 2 imes s_{i-1} ]

    而且,由于(a)数组任意时刻都是非负的。所以(s)也是单调不下降的。

    那我们就可以从(1)开始,然后每次找到第一个大于等于(2*当前值)的位置,看看是否合法,然后跳过去,继续下一次的过程。

    这样可以严格证明复杂度是(log)的(可以理解为最多(log)次,就加到极限了)

    int solve()
    {
     int now=0;
     ll uu=0;
     while(now!=n)
     {
      int nxt = getpos(1,1,n,2*uu);
      //if (query(1,1,n,nxt-1)*2==query(1,1,n,nxt)) return nxt;
      if(kachang == 2*a[nxt]) return nxt; 
      now=nxt;
      uu=kachang; 
     }
     return -1;
    }
    

    计算第一个大于等于某个数的过程,我们可以直接选择再线段树上二分,这样复杂度是(log)的,如果要是不在线段树上二分,可能需要两个(log)的时间

    int getpos(int root,int l,int r,ll lim)
    { 
     if (l==r) 
     {
       kachang = f[root];
       return l;
     }
     pushdown(root,l,r);
     int mid = l+r >> 1;
     if (f[root<<1]>=lim) return getpos(root<<1,l,mid,lim);
     else return getpos(root<<1|1,mid+1,r,lim); 
    }
    

    (而且这个题会卡常,我这里贴的代码都是卡常之后的,可能比较难理解)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define mk makr_pair
    #define ll long long
    using namespace std;
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    const int maxn = 4e5+1e2;
    ll f[4*maxn];
    ll add[4*maxn];
    int n,m;
    int pos,ans;
    ll sum[maxn],a[maxn];
    void up(int root)
    {
     f[root]=max(f[root<<1],f[root<<1|1]);
    } 
    void pushdown(int root,int l,int r)
    {
     if (add[root])
     {
      add[root<<1]+=add[root];
      add[root<<1|1]+=add[root];
      f[root<<1]+=add[root];
      f[root<<1|1]+=add[root];
      add[root]=0;
     }
    }
    void build(int root,int l,int r)
    {
     if (l==r)
     {
      f[root]=sum[l];
      return;
     }
     int mid = l+r >> 1;
     build(root<<1,l,mid);
     build(root<<1|1,mid+1,r);
     up(root);
    }
    void update(int root,int l,int r,int x,int y,ll p)
    {
     if (x<=l && r<=y)
     {
      f[root]+=p;
      add[root]+=p;
      return;
     }
     pushdown(root,l,r);
     int mid = l+r >> 1;
     if (x<=mid) update(root<<1,l,mid,x,y,p);
     if (y>mid) update(root<<1|1,mid+1,r,x,y,p);
     up(root);
    }
    ll query(int root,int l,int r,int x)
    {
     if (x==0) return 0;
     if (l==r)
     {
      return f[root];
     }
     pushdown(root,l,r);
     int mid = l+r >> 1;
        ll ans = -1e18;
        if (x<=mid) ans=max(ans,query(root<<1,l,mid,x));
     if (x>mid) ans=max(ans,query(root<<1|1,mid+1,r,x));
        return ans; 
    }
    long long kachang;
    int getpos(int root,int l,int r,ll lim)
    { 
     if (l==r) 
     {
       kachang = f[root];
       return l;
     }
     pushdown(root,l,r);
     int mid = l+r >> 1;
     if (f[root<<1]>=lim) return getpos(root<<1,l,mid,lim);
     else return getpos(root<<1|1,mid+1,r,lim); 
    }
    int solve()
    {
     int now=0;
     ll uu=0;
     while(now!=n)
     {
      int nxt = getpos(1,1,n,2*uu);
      //if (query(1,1,n,nxt-1)*2==query(1,1,n,nxt)) return nxt;
      if(kachang == 2*a[nxt]) return nxt; 
      now=nxt;
      uu=kachang; 
     }
     return -1;
    }
    signed main()
    {
      n=read();m=read();
      for (register int i=1;i<=n;++i) a[i]=read();
      for (register int i=1;i<=n;++i) sum[i]=sum[i-1]+a[i];
      build(1,1,n);
      for (register int i=1;i<=m;++i)
      {
        int x=read(),y=read();
        update(1,1,n,x,n,y-a[x]);
        a[x]=y;
        cout<<solve()<<"
    ";
      }
      return 0;
    }
    
    
  • 相关阅读:
    .Net魔法堂:log4net详解
    CentOS6.5菜鸟之旅:安装SUN JDK1.7和Tomcat7
    Java魔法堂:注释和注释模板
    Eclipse魔法堂:任务管理器
    CentOS6.5菜鸟之旅:VirtualBox4.3识别USB设备
    Windows魔法堂:解决“由于启动计算机时出现页面文件配置问题.......”
    JS魔法堂:IE5~9的Drag&Drop API
    CentOS6.5菜鸟之旅:安装VirtualBox4.3
    HTML5魔法堂:全面理解Drag & Drop API
    byzx
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10161964.html
Copyright © 2020-2023  润新知