zoukankan      html  css  js  c++  java
  • 【BZOJ2138】stone

    题面

    http://darkbzoj.tk/problem/2138

    题解

    用类前缀和维护在给定的区间内的所有区间的价值之和,再用线段树维护区间最值。

    把求全局最值转换成求当前区间左右最值那一步非常妙,是为了求出这块区域最多能被拿走多少块石子。

    #include<stack>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define N 45000
    #define ri register int
    using namespace std;
    
    int a[N],k[N],sum[N];
    int n,m;
    
    inline int read() {
      int ret=0,f=0; char ch=getchar();
      while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
      while (ch>='0' && ch<='9') ret*=10,ret+=(ch-'0'),ch=getchar();
      return f?-ret:ret;
    }
    
    int sqr(int x) {
      return x*x;
    }
    
    struct segment_tree {
      int t1[N<<2],t2[N<<2];
      int tag1[N<<2],tag2[N<<2];
      void maketree(int x,int l,int r) {
        if (l==r) {
          t1[x]=t2[x]=sum[l];
          return;
        }
        int mid=(l+r)/2;
        maketree(x<<1,l,mid); maketree(x<<1|1,mid+1,r);
        t1[x]=max(t1[x<<1],t1[x<<1|1]);
        t2[x]=min(t2[x<<1],t2[x<<1|1]);
      }
      void pushdown1(int x) {
        int k=tag1[x]; tag1[x]=0;
        t1[x<<1]+=k;   tag1[x<<1]+=k;
        t1[x<<1|1]+=k; tag1[x<<1|1]+=k;
      }
      void pushdown2(int x) {
        int k=tag2[x]; tag2[x]=0;
        t2[x<<1]+=k;   tag2[x<<1]+=k;
        t2[x<<1|1]+=k; tag2[x<<1|1]+=k;
      }
      void modify1(int x,int lb,int rb,int l,int r,int k) {
        if (l<=lb && rb<=r) {
          t1[x]+=k; tag1[x]+=k;
          return;
        }
        if (l>rb || r<lb) return;
        pushdown1(x);
        int mid=(lb+rb)/2;
        modify1(x<<1,lb,mid,l,r,k); modify1(x<<1|1,mid+1,rb,l,r,k);
        t1[x]=max(t1[x<<1],t1[x<<1|1]);
      }
      void modify2(int x,int lb,int rb,int l,int r,int k) {
        if (l<=lb && rb<=r) {
          t2[x]+=k; tag2[x]+=k;
          return;
        }
        if (l>rb || r<lb) return;
        pushdown2(x);
        int mid=(lb+rb)/2;
        modify2(x<<1,lb,mid,l,r,k); modify2(x<<1|1,mid+1,rb,l,r,k);
        t2[x]=min(t2[x<<1],t2[x<<1|1]);
      }
      int query1(int x,int lb,int rb,int l,int r) {
        if (l<=lb && rb<=r) return t1[x];
        if (l>rb || r<lb) return -1e9;
        pushdown1(x);
        int mid=(lb+rb)/2;
        return max(query1(x<<1,lb,mid,l,r),query1(x<<1|1,mid+1,rb,l,r));
      }
      int query2(int x,int lb,int rb,int l,int r) {
        if (l<=lb && rb<=r) return t2[x];
        if (l>rb || r<lb) return 1e9;
        pushdown2(x);
        int mid=(lb+rb)/2;
        return min(query2(x<<1,lb,mid,l,r),query2(x<<1|1,mid+1,rb,l,r));
      }
    } T;
    
    int main() {
      n=read();
      int x=read(),y=read(),z=read(),p=read();
      for (ri i=1;i<=n;i++) a[i]=(sqr(i-x)+sqr(i-y)+sqr(i-z))%p;
      m=read();
      k[1]=read(); k[2]=read(); x=read(),y=read(),z=read(),p=read();
      for (ri i=3;i<=m;i++) k[i]=(x*k[i-1]+y*k[i-2]+z)%p;
      for (ri i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
      T.maketree(1,1,n);
      for (ri i=1;i<=m;i++) {
        int l=read(),r=read();
        k[i]=min(k[i],T.query2(1,1,n,r,n)-max(T.query1(1,1,n,1,l-1),0));
        printf("%d
    ",k[i]);
        T.modify1(1,1,n,l,n,-k[i]); T.modify2(1,1,n,r,n,-k[i]);
      }
      return 0;
    }
  • 相关阅读:
    前后台验证字符串长度
    接口和抽象类该什么时候用?
    程序员常去网站汇总
    SQLServer复合查询条件(AND,OR,NOT)对NULL值的处理方法
    c#-轮询算法
    常用的SQL语句
    HTTP请求工具类
    asp.net mvc jQuery 城市二级联动
    ibatis动态多条件查询及模糊查询(oracle,mysql,sql)
    iBatis 中 Like 的写法实现模糊查询
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11323893.html
Copyright © 2011-2022 走看看