zoukankan      html  css  js  c++  java
  • 2016暑假多校联合---Rikka with Sequence (线段树)

    2016暑假多校联合---Rikka with Sequence (线段树)

    Problem Description
    As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

    Yuta has an array A with n numbers. Then he makes m operations on it. 

    There are three type of operations:

    1 l r x : For each i in [l,r], change A[i] to A[i]+x
    2 l r : For each i in [l,r], change A[i] to A−−√[i]
    3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r]

    It is too difficult for Rikka. Can you help her?
     
    Input
    The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000.

    For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.

    It is guaranteed that 1<=A[i],x<=100000.
     
    Output
    For each operation of type 3, print a lines contains one number -- the answer of the query.
     
    Sample Input
    1
    5 5
    1 2 3 4 5
    1 3 5 2
    2 1 4
    3 2 4
    2 3 5
    3 1 5
     
    Sample Output
    5
    6
     
    Author
    学军中学
     
    Source
     
    Recommend
    wange2014   |   We have carefully selected several similar problems for you:  5831 5830 5829 5827 5826 
     

    题意: 三种操作,1、区间上加上一个数;
                           2、区间上所有数开根号向下取整;
                           3、区间求和;

    思路: 对于记录区间的最大值和最小值,如果相等的话,那么只需要对一个数开根号,算出开根号前后的差值,这样区间开根号就变成了区间减去一个数了; 
             由于是开根,所以存在两个数刚开始差为1,加上某数再开根依旧是差1,这样维护相同数区间的就没用了
             比如(2,3) +6-->(8,9)开根-->(2,3)如果全是这样的操作,即使维护相同的数,每次开根的复杂度都是O(N),不T才怪
             这样只需要维护区间最大值最小值,当差1的时候,看看是否开根后还是差1,如果还是差1,那么对区间开根号相当于整个区间减去同一个数,
             这样就可以变开根为减了

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar()
    {
        if(head==tail)
        {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read()
    {
        int x=0,f=1;char c=Getchar();
        for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
        return x*f;
    }
    ///----------------------------------------------------------------------
    const int N=1e5+5;
    LL sum[N<<2],lz[N<<2],mx[N<<2],mn[N<<2];
    
    void up(int rt)
    {
      sum[rt]=sum[rt<<1]+sum[rt<<1|1];
      mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
      mn[rt]=min(mn[rt<<1],mn[rt<<1|1]);
    }
    
    void build(int rt,int l,int r)
    {
      lz[rt]=0;
      if(l==r){sum[rt]=read();mn[rt]=mx[rt]=sum[rt];return;}
      int mid=l+r>>1;
      build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
      up(rt);
    }
    
    void down(int rt,int l,int r)
    {
      if(lz[rt]!=0)
      {
        int mid=l+r>>1;
        lz[rt<<1]+=lz[rt];
        lz[rt<<1|1]+=lz[rt];
        mn[rt<<1]+=lz[rt];
        mx[rt<<1]+=lz[rt];
        mx[rt<<1|1]+=lz[rt];
        mn[rt<<1|1]+=lz[rt];
        sum[rt<<1]+=lz[rt]*(mid-l+1);
        sum[rt<<1|1]+=lz[rt]*(r-mid);
        lz[rt]=0;
      }
    }
    
    int x,y,t,T,n,m;
    
    void kaigen(int rt,int l,int r)
    {
      if(x<=l&&r<=y)
      {
         if(mx[rt]==mn[rt])
         {
            lz[rt]-=mx[rt];
            mx[rt]=sqrt(mx[rt]);
            mn[rt]=mx[rt];
            lz[rt]+=mx[rt];
            sum[rt]=mx[rt]*(r-l+1);
            return;
         }
         else if(mx[rt]==mn[rt]+1)
         {
           LL x1=sqrt(mx[rt]);
           LL x2=sqrt(mn[rt]);
           if(x1==x2+1)
           {
              lz[rt]-=(mx[rt]-x1);
              sum[rt]-=(mx[rt]-x1)*(r-l+1);
              mx[rt]=x1;mn[rt]=x2;
              return;
           }
        }
      }
      int mid=l+r>>1;down(rt,l,r);
      if(x<=mid)kaigen(rt<<1,l,mid);
      if(y>mid)kaigen(rt<<1|1,mid+1,r);
      up(rt);
    }
    
    void add(int rt,int l,int r)
    {
      if(x<=l&&r<=y)
      {
        lz[rt]+=t;
        sum[rt]+=(long long)(r-l+1)*t;
        mx[rt]+=t;mn[rt]+=t;
        return ;
      }
      int mid=l+r>>1;down(rt,l,r);
      if(x<=mid)add(rt<<1,l,mid);
      if(y>mid)add(rt<<1|1,mid+1,r);
      up(rt);
    }
    
    LL get(int rt,int l,int r)
    {
      if(x<=l&&r<=y)return sum[rt];
      int mid=l+r>>1;down(rt,l,r);
      LL ret=0;
      if(x<=mid)ret+=get(rt<<1,l,mid);
      if(y>mid)ret+=get(rt<<1|1,mid+1,r);
      return ret;
    }
    
    int main()
    {
      T=read();
      while(T--)
      {
        n=read();m=read();
        build(1,1,n);
        while(m--)
        {
          int op;
          op=read();x=read();y=read();
          if(op==1)
          {
            t=read();
            add(1,1,n);
          }
          else if(op==2)kaigen(1,1,n);
          else printf("%I64d
    ",get(1,1,n));
        }
      }
      return 0;
    }
     
  • 相关阅读:
    第一遍机房收费系统总结
    HDU 4027 Can you answer these queries?(线段树)
    程序猿的路----程序猿一定要细致看
    让你提前认识软件开发(25):数据库简单介绍
    could not initialize proxy
    ios--uitextfield动态限制输入的字数(解决方式)
    Python 学习之二:Python超短教程
    【v2.x OGE教程 19】 引擎状态控制
    [MongoDB]count,gourp,distinct
    [MongoDB]增删改查
  • 原文地址:https://www.cnblogs.com/chen9510/p/5765865.html
Copyright © 2011-2022 走看看