Rikka with Sequence

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5828

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
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(11000.
For each testcase, the first line contains two numbers n,m(1

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

Source


2016 Multi-University Training Contest 8


##题意:

对一个数组进行若干操作:
1. 将区间内的值都加x.
2. 将区间内的值都开平方.
3. 求区间内数的和.


##题解:

容易想到用线段树来维护,关键是如何处理操作二. 直接对每个数开平方肯定会超时.
考虑到开平方操作的衰减速度很快,一个数最多经过6次开平方操作就会到1.
那么随着操作的进行,区间内的数会趋于相同,恰好利用这个点来作剪枝.
对于树中的每个结点维护一个equal, 表示当前结点的子节点是否相等. (若相等就等于子节点的值,否则为-1).
当更新到某区间时,若区间内的值都相同,则只更新到这里即可,下面的结点利用pushdown来更新.

赛后数据被加强了,上述思路在HDU上已经AC不了了. sad....


##代码:
``` cpp
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define eps 1e-8
#define maxn 101000
#define mod 100000007
#define inf 0x3f3f3f3f
#define mid(a,b) ((a+b)>>1)
#define IN freopen("in.txt","r",stdin);
using namespace std;

int n;

LL num[maxn];

struct Tree

{

int left,right;

LL lazy,sum,equl;

}tree[maxn<<2];

void build(int i,int left,int right)

{

tree[i].left=left;

tree[i].right=right;

tree[i].lazy=0;

  1. if(left==right){
  2. tree[i].sum = num[left];
  3. tree[i].equl = num[left];
  4. return ;
  5. }
  6. int mid=mid(left,right);
  7. build(i<<1,left,mid);
  8. build(i<<1|1,mid+1,right);
  9. tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
  10. tree[i].equl = tree[i<<1].equl==tree[i<<1|1].equl ? tree[i<<1].equl : -1;

}

void pushdown(int i)

{

if(tree[i].equl != -1) {

tree[i<<1].equl = tree[i].equl;

tree[i<<1|1].equl = tree[i].equl;

tree[i<<1].sum = (tree[i<<1].right-tree[i<<1].left+1)tree[i].equl;

tree[i<<1|1].sum = (tree[i<<1|1].right-tree[i<<1|1].left+1)
tree[i].equl;

tree[i].lazy = 0;

tree[i<<1].lazy = 0;

tree[i<<1|1].lazy = 0;

}

if(tree[i].lazy) {

tree[i<<1].lazy += tree[i].lazy;

tree[i<<1|1].lazy += tree[i].lazy;

tree[i<<1].sum += (tree[i<<1].right-tree[i<<1].left+1)tree[i].lazy;

tree[i<<1|1].sum += (tree[i<<1|1].right-tree[i<<1|1].left+1)
tree[i].lazy;

if(tree[i<<1].equl != -1) {

tree[i<<1].equl += tree[i].lazy;

tree[i<<1].lazy = 0;

}

if(tree[i<<1|1].equl != -1) {

tree[i<<1|1].equl += tree[i].lazy;

tree[i<<1|1].lazy = 0;

}

tree[i].lazy = 0;

}

}

void update(int i,int left,int right,LL d)

{

if(tree[i].leftleft&&tree[i].rightright)

{

tree[i].sum += (right-left+1)*d;

if(tree[i].equl == -1) tree[i].lazy += d;

else tree[i].equl += d;

return ;

}

  1. pushdown(i);
  2. int mid=mid(tree[i].left,tree[i].right);
  3. if(right<=mid) update(i<<1,left,right,d);
  4. else if(left>mid) update(i<<1|1,left,right,d);
  5. else {
  6. update(i<<1,left,mid,d);
  7. update(i<<1|1,mid+1,right,d);
  8. }
  9. tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
  10. tree[i].equl = tree[i<<1].equl==tree[i<<1|1].equl ? tree[i<<1].equl : -1;

}

void update_sqrt(int i,int left,int right)

{

if(tree[i].leftleft&&tree[i].rightright && tree[i].equl!=-1)

{

tree[i].equl = (LL)sqrt(tree[i].equl);

tree[i].sum = tree[i].equl * (tree[i].right-tree[i].left+1);

tree[i].lazy = 0;

return ;

}

  1. pushdown(i);
  2. int mid=mid(tree[i].left,tree[i].right);
  3. if(right<=mid) update_sqrt(i<<1,left,right);
  4. else if(left>mid) update_sqrt(i<<1|1,left,right);
  5. else {
  6. update_sqrt(i<<1,left,mid);
  7. update_sqrt(i<<1|1,mid+1,right);
  8. }
  9. tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
  10. tree[i].equl = tree[i<<1].equl==tree[i<<1|1].equl ? tree[i<<1].equl : -1;

}

LL query(int i,int left,int right)

{

if(tree[i].leftleft&&tree[i].rightright)

return tree[i].sum;

  1. pushdown(i);
  2. int mid=mid(tree[i].left,tree[i].right);
  3. if(right<=mid) return query(i<<1,left,right);
  4. else if(left>mid) return query(i<<1|1,left,right);
  5. else return query(i<<1,left,mid)+query(i<<1|1,mid+1,right);

}

int main(int argc, char const *argv[])

{

//IN;

  1. int t; cin >> t;
  2. while(t--)
  3. {
  4. int m;
  5. scanf("%d %d", &n,&m);
  6. for(int i=1; i<=n; i++)
  7. scanf("%lld", &num[i]);
  8. build(1, 1, n);
  9. while(m--) {
  10. int op, l, r;
  11. scanf("%d %d %d", &op,&l,&r);
  12. if(op == 1) {
  13. LL x; scanf("%lld", &x);
  14. update(1, l, r, x);
  15. }
  16. else if(op == 2) {
  17. update_sqrt(1, l, r);
  18. }
  19. else if(op == 3) {
  20. printf("%lld\n", query(1, l, r));
  21. }
  22. }
  23. }
  24. return 0;

}

HDU 5828 Rikka with Sequence (线段树)的更多相关文章

  1. hdu 5828 Rikka with Sequence 线段树

    Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...

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

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...

  3. HDU 5828 Rikka with Sequence(线段树区间加开根求和)

    Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...

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

    2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...

  5. 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence

    // 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...

  6. HDU 5828 Rikka with Sequence(线段树 开根号)

    Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  7. hdu 4893 Wow! Such Sequence!(线段树)

    题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 改动k的为值添加d 2 l r, 查询l到r的区间和 3 l r. 间l到r区间上的所以数变成 ...

  8. HDU 6089 Rikka with Terrorist (线段树)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6089 题解 这波强行维护搞得我很懵逼... 扫描线,只考虑每个点能走到左上方(不包括正上方,但包括正左 ...

  9. HDU 5634 Rikka with Phi 线段树

    题意:bc round 73 div1 D 中文题面 分析:注意到10^7之内的数最多phi O(log(n))次就会变成1, 因此可以考虑把一段相同的不为1的数缩成一个点,用平衡树来维护. 每次求p ...

随机推荐

  1. View的个得区域函数getHitRect,getDrawingRect,getLocalVisibleRect,getGlobalVisibleRect(*)

    注意: OnCreate()函数中 调用下面函数,结果全为0,要等UI控件都加载完了才能得到绘制时的值. getHitRect 以父控件的左上为原点,计算当前view在父控件的区域,不管父控件在屏幕的 ...

  2. Samba 4.x.x全版本存在命令执行漏洞

    Samba 4.0.0到4.1.10版本的nmbd(the NetBIOS name services daemon)被发现存在远程命令执行漏洞.CVE编号为CVE-2014-3560.目前官方已经发 ...

  3. HNOI2010弹飞绵羊

    不得不说块状数组好神奇的啊!这道题的标签可是splay的启发是合并(什么高大上的东西),竟然这么轻松的就解决了! var x,y,i,j,tot,n,m,ch:longint; f,k,l,bl,go ...

  4. Android adb install INSTALL_FAILED_DEXOPT

    说明: 之前一直认为将eclipse的Android项目直接cp到Android源码下编译就行了,实际情况是还要注意其他的文件架构. 错误现象: c:\Users\zengjf>adb inst ...

  5. 【linux】命令

    pwd 显示路径 whereis jupyterhub find / -name base.py reboot 重启 grep

  6. Java [Leetcode 67]Add Binary

    题目描述: Given two binary strings, return their sum (also a binary string). For example,a = "11&qu ...

  7. Java [Leetcode 231]Power of Two

    题目描述: Given an integer, write a function to determine if it is a power of two. 解题思路: 判断方法主要依据2的N次幂的特 ...

  8. javaScript的函数(Function)对象的声明(@包括函数声明和函数表达式)

    写作缘由: 平时再用js写函数的时候,一般都是以惯例 function fn () {} 的方式来声明一个函数,在阅读一些优秀插件的时候又不免见到 var fn = function () {} 这种 ...

  9. shell -Z- d等等代表

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 [ -a FILE ]   ...

  10. [Papers]NSE, $u_3$, Lebesgue space [Zhou-Pokorny, Nonlinearity, 2009]

    $$\bex u_3\in L^p(0,T;L^q(\bbR^3)),\quad \frac{2}{p}+\frac{3}{q}=\frac{3}{4}+\frac{1}{2q},\quad \fra ...