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;
    }
     
  • 相关阅读:
    selenium 8大元素定位方法
    selenium环境安装及简单使用
    Python json序列化和反序列化
    pytest使用allure生成测试报告
    Windows10下JDK15的安装教程
    Ansible:服务器巡检_3、Windows 平台巡检
    转载:shell中各种括号的作用详解()、(())、[]、[[]]、{}(推荐)
    Tips: Linux 中 当形参名称是 变量时,如何取出全部的实参
    Python 问题记录:XXX.whl is not a supported wheel on this platform.
    Ansible:服务器巡检_2、Linux 服务器巡检脚本
  • 原文地址:https://www.cnblogs.com/chen9510/p/5765865.html
Copyright © 2011-2022 走看看