• zjoi[ZJOI2018]胖


    题解:

    因为n,m很大

    所以复杂度应该是和m相关的

    考虑到每个点的影响区间是连续的

    就很简单了

    区间查询最小值线段树维护(st表也可以)

    然后注意一下不要重复算一个就可以了

    max函数用template<class T> 不能与原来min重名

    代码:

    #pragma GCC optimize(2)
    #include <bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define IL inline
    #define rint register int
    #define rep(i,h,t) for (rint i=h;i<=t;i++)
    #define dep(i,t,h) for (rint i=t;i>=h;i--)
    const int N=3e5;
    const ll INF=1e18; 
    const int N2=1e7; 
    ll dis[N],sum1[N],sum2[N];
    int n,m,cnt;
    struct re{
      int a;
      ll b;
    };
    vector<int> ve;
    ll data1[N2],data2[N2];
    int ls[N2],rs[N2];
    char ss[1<<27],*A=ss,*B=ss;
    IL char gc()
    {
      return (A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++); 
    }
    template<class T>void read(T &x)
    {
      rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=c^48;
      while (c=gc(),47<c&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
    }
    char sr[1<<24],z[20]; int C=-1,Z;
    template <class T> void wer(T x)
    {
      if (x<0) sr[++C]='-',x=-x;
      while (z[++Z]=x%10+48,x/=10);
      while (sr[++C]=z[Z],--Z); sr[++C]='
    ';
    }
    template<class T> T MAX(T x,T y)
    {
      if (x>y) return(x); else return(y);
    }
    template<class T> T MIN(T x,T y)
    {
      if (x<y) return(x); else return(y);
    }
    IL void swap(int &x,int &y)
    {
      int tmp=x; x=y; y=tmp;
    }
    void clear()
    {
      cnt=0;
      for (int i=0;i<ve.size();i++)
      {
        int x=ve[i];
        data1[x]=INF; data2[x]=INF; ls[x]=0; rs[x]=0;
      }
      ve.clear();
    }
    void updata(int x)
    {
      data1[x]=MIN(data1[ls[x]],data1[rs[x]]);
      data2[x]=MIN(data2[ls[x]],data2[rs[x]]);
    }
    void change(int &x,int h,int t,int pos,ll k)
    {
      if (!x) x=++cnt;
      ve.push_back(x);
      if (h==t)
      {
        data1[x]=MIN(data1[x],sum1[pos-1]+k);
        data2[x]=MIN(data2[x],sum2[pos]+k);
        return;
      }
      int mid=(h+t)/2;
      if (pos<=mid) change(ls[x],h,mid,pos,k);
      else change(rs[x],mid+1,t,pos,k);
      updata(x);
    }
    ll query1(int x,int h,int t,int h1,int t1)
    {
      if (!x) return(INF);
      if (h1<=h&&t<=t1) return(data1[x]);
      ll ans=INF;
        int mid=(h+t)/2;
      if (h1<=mid) ans=query1(ls[x],h,mid,h1,t1);
      if (mid<t1) ans=MIN(ans,query1(rs[x],mid+1,t,h1,t1));
      return(ans);
    }
    ll query2(int x,int h,int t,int h1,int t1)
    {
      if (!x) return(INF);
      if (h1<=h&&t<=t1) return(data2[x]);
      ll ans=INF;
        int mid=(h+t)/2;
      if (h1<=mid) ans=query2(ls[x],h,mid,h1,t1);
      if (mid<t1) ans=MIN(ans,query2(rs[x],mid+1,t,h1,t1));
      return(ans);
    }
    IL ll check1(int h,int t,int x)
    {
      h=MAX(h,1); t=MIN(t,n);
      return(query2(1,1,n,h,t)-sum2[x]);
    }
    IL ll check2(int h,int t,int x)
    {
      h=MAX(h,1); t=MIN(t,n);
      return(query1(1,1,n,h,t)-sum1[x-1]);
    }
    int main()
    {
      read(n); read(m);
      rep(i,1,n-1) read(dis[i]);
      rep(i,1,n-1) sum1[i]=dis[i],sum1[i]+=sum1[i-1];
      dep(i,n-1,1) sum2[i]=dis[i],sum2[i]+=sum2[i+1];
      rep(i,0,N2-1) data1[i]=INF,data2[i]=INF;
      rep(i,1,m)
      {
        int x,y;
        ll ans=0,z;
        read(x);
        vector<re> ve1;
        ve1.push_back((re){0,0});
        clear();
        int root=0;
        rep(j,1,x)
        {
          read(y); read(z);
          change(root,1,n,y,z);
          ve1.push_back((re){y,z});
        }
        rep(j,1,x)
        {
          int y=ve1[j].a;
          ll z=ve1[j].b;
          int h=y,t=n;
          while (h<t)
          {
            int mid=(h+t+1)/2;
            ll jl=sum1[mid-1]-sum1[y-1]+z;
            if (MIN(check1(y+1,mid,mid),check2(mid,2*mid-y-1,mid))>jl&&
               check2(2*mid-y,2*mid-y,mid)>=jl) h=mid;
            else t=mid-1;
          }
          ans+=t-y;
          h=1,t=y;
          while (h<t)
          {
            int mid=(h+t)/2;
            ll jl=sum1[y-1]-sum1[mid-1]+z;
            if (MIN(check2(mid,y-1,mid),check1(2*mid-y+1,mid,mid))>jl&&
                check1(2*mid-y,2*mid-y,mid)>jl) t=mid;
            else h=mid+1;
          }
          ans+=y-h+1;
        }
        wer(ans);
      }
      fwrite(sr,1,C+1,stdout);
      return 0;
    }
  • 相关阅读:
    2008秋季计算机软件基础点名册应用化学制药工程
    2008秋季计算机软件基础实验进程表应用化学制药工程
    格式化JavaScript代码
    MIME类型,MIME 参考
    2008秋季计算机软件基础0827课堂用例
    2008秋季解读大纲:计算机软件基础
    2008秋季计算机软件基础C语言精简课件
    2008秋季计算机软件基础应用化学制药工程授课日历
    几款JavaScript开发框架、开发库
    2008秋季计算机软件基础作业和实验报告注意事项
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/9164795.html
Copyright © 2020-2023  润新知