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

2016 Multi-University Training Contest 8

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\n",get(1,1,n));
    }
  }
  return 0;
}
时间: 2024-10-10 14:46:20

2016暑假多校联合---Rikka with Sequence (线段树)的相关文章

2016暑假多校联合---Windows 10

2016暑假多校联合---Windows 10(HDU:5802) Problem Description Long long ago, there was an old monk living on the top of a mountain. Recently, our old monk found the operating system of his computer was updating to windows 10 automatically and he even can't j

2016暑假多校联合---Substring(后缀数组)

2016暑假多校联合---Substring Problem Description ?? is practicing his program skill, and now he is given a string, he has to calculate the total number of its distinct substrings. But ?? thinks that is too easy, he wants to make this problem more interesti

2016暑假多校联合---Another Meaning

2016暑假多校联合---Another Meaning Problem Description As is known to all, in many cases, a word has two meanings. Such as “hehe”, which not only means “hehe”, but also means “excuse me”. Today, ?? is chating with MeiZi online, MeiZi sends a sentence A to

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

2014多校3 Wow! Such Sequence!线段树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 这题实在是让人纠结啊--好久不写线段树的题了,因为这几天学伸展树,然后觉得线段树小case了.没想到栽在这题上了.尼玛-- 自己把自己给搞晕了--想复杂了,都不懂得预处理一下,唉--还得怒刷几十道啊!! #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #in

2016暑假多校联合---Death Sequence(递推、前向星)

原题链接 Problem Description You may heard of the Joseph Problem, the story comes from a Jewish historian living in 1st century. He and his 40 comrade soldiers were trapped in a cave, the exit of which was blocked by Romans. They chose suicide over captu

2016暑假多校联合---Joint Stacks (STL)

HDU  5818 Problem Description A stack is a data structure in which all insertions and deletions of entries are made at one end, called the "top" of the stack. The last entry which is inserted is the first one that will be removed. In another wor

2016暑假多校联合---Counting Intersections

原题链接 Problem Description Given some segments which are paralleled to the coordinate axis. You need to count the number of their intersection. The input data guarantee that no two segments share the same endpoint, no covered segments, and no segments

HDU 5828 Rikka with Sequence (线段树+剪枝优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是求出l到r之间的和. 操作1和3就不说了,关键是开方操作. 一个一个开方,复杂度太高,无疑会T.所以我们来剪枝一下. 我们可以观察,这里一个数最多开方4,5次(loglogx次)就会到1,所以要是一段区间最大值为1的话,就不需要递归开方下去了.这是一个剪枝. 如果一段区间的数都是一样大小(最大值等于