【HDU 5828】Rikka with Sequence(线段树)
来源:互联网 发布:mysql my.ini配置 编辑:程序博客网 时间:2024/06/08 06:32
Rikka with Sequence
Total Submission(s): 2311 Accepted Submission(s): 391
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?
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(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.
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
题目大意:
区间三种操作。
1 区间加
2 区间开根
3 区间求和
第一个和第三个用Lazy外加合并相同区间。时间很充裕
开根和区间加不一样的是与元素本身有关。所以很爆炸的要找到每一个叶子。
如果单单这样其实最差的复杂度只会在构造出这种序列后的第一次开根。
但是有一种特殊情况,类似
这样如果序列是交错排列的2 3 2 3 2 3 2 3,然后对区间不断+6 开根 +6 开根,就退化到了单次
这组数据是在赛后加的,当时一片片TLE……现在一瞅过了不少,然后百度了一下发现有人发了更优美的题解,然后就来补了一下。
开根的处理就是除了维护区间和外,再维护一个区间最大mx与最小mn。
当区间mx-mn <= 1 && sqrt(mx)-sqrt(mn) <= 1,就可以cut了,因为开根前后差值是一样的,就变为了区间减法,lazy标记一下就可以了
另发现绝版输入挂,常数优化绝妙
代码如下:
#include <iostream>#include <cmath>#include <vector>#include <cstdlib>#include <cstdio>#include <climits>#include <ctime>#include <cstring>#include <queue>#include <stack>#include <list>#include <algorithm>#include <map>#include <set>#define LL long long#define Pr pair<int,int>#define frd(ch) freopen(ch,"r",stdin)#define fwrite(ch) freopen(ch,"w",stdout)using namespace std;const int INF = 0x3f3f3f3f;const int msz = 112345;const int mod = 1e9+7;const double eps = 1e-8;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;}LL sum[4*msz],mx[4*msz],mn[4*msz],lz[4*msz];void down(int root,int l,int r){ if(!lz[root]) return; int mid = (l+r)>>1; mx[root<<1] += lz[root]; mx[root<<1|1] += lz[root]; mn[root<<1] += lz[root]; mn[root<<1|1] += lz[root]; sum[root<<1] += lz[root]*(mid-l+1); sum[root<<1|1] += lz[root]*(r-mid); lz[root<<1] += lz[root]; lz[root<<1|1] += lz[root]; lz[root] = 0;}void up(int root){ sum[root] = sum[root<<1]+sum[root<<1|1]; mx[root] = max(mx[root<<1],mx[root<<1|1]); mn[root] = min(mn[root<<1],mn[root<<1|1]);}void Add(int root,int l,int r,int ll,int rr,LL ad){ if(l == ll && r == rr) { lz[root] += ad; sum[root] += ad*(r-l+1); mx[root] += ad; mn[root] += ad; return; } int mid = (l+r)>>1; down(root,l,r); if(mid >= rr) Add(root<<1,l,mid,ll,rr,ad); else if(mid+1 <= ll) Add(root<<1|1,mid+1,r,ll,rr,ad); else { Add(root<<1,l,mid,ll,mid,ad); Add(root<<1|1,mid+1,r,mid+1,rr,ad); } up(root);}LL Sum(int root,int l,int r,int ll,int rr){ if(l == ll && r == rr) { return sum[root]; } int mid = (l+r)>>1; down(root,l,r); if(mid >= rr) return Sum(root<<1,l,mid,ll,rr); else if(mid+1 <= ll) return Sum(root<<1|1,mid+1,r,ll,rr); return Sum(root<<1,l,mid,ll,mid)+Sum(root<<1|1,mid+1,r,mid+1,rr);}void Sqrt(int root,int l,int r,int ll,int rr){ //printf("[%d,%d] mx%lld mn%lld\n",l,r,mx[root],mn[root]); if(l == ll && r == rr) { LL cut; if(mx[root] == mn[root]) { cut = mx[root]-floor(sqrt(mx[root]*1.0)); lz[root] -= cut; sum[root] -= cut*(r-l+1); mx[root] = mn[root] = mx[root]-cut; return; } else if(mx[root]-mn[root] == 1) { LL t1,t2; t1 = floor(sqrt(mx[root]*1.0)); t2 = floor(sqrt(mn[root]*1.0)); if(t1-t2 == 1) { cut = mx[root]-t1; lz[root] -= cut; sum[root] -= cut*(r-l+1); mx[root] = t1; mn[root] = t2; return; } } } int mid = (l+r)>>1; down(root,l,r); if(mid >= rr) Sqrt(root<<1,l,mid,ll,rr); else if(mid+1 <= ll) Sqrt(root<<1|1,mid+1,r,ll,rr); else { Sqrt(root<<1,l,mid,ll,mid); Sqrt(root<<1|1,mid+1,r,mid+1,rr); } up(root);}void init(int root,int l,int r){ lz[root] = 0; if(l == r) { sum[root] = read(); mx[root] = mn[root] = sum[root]; return; } int mid = (l+r)>>1; init(root<<1,l,mid); init(root<<1|1,mid+1,r); up(root);}int main(){ //frd("1008.in"); //fwrite("m.out"); int t,opt,l,r,x,n,q; t = read(); while(t--) { n = read(); q = read(); init(1,1,n); while(q--) { opt = read(); l = read(); r = read(); if(opt == 1) { x = read(); Add(1,1,n,l,r,x); } else if(opt == 2) { Sqrt(1,1,n,l,r); } else printf("%lld\n",Sum(1,1,n,l,r)); } } return 0;}
0 0
- HDU 5828 Rikka with Sequence(线段树+小优化)
- HDU 5828 Rikka with Sequence(线段树)
- Hdu-5828 Rikka with Sequence(线段树)
- HDU-5828-Rikka with Sequence(线段树)
- 【HDU 5828】Rikka with Sequence(线段树)
- HDU 5828 Rikka with Sequence(线段树)
- 线段树,区间开方(Rikka with Sequence,HDU 5828)
- hdu 5828 Rikka with Sequence 【线段树+优化】
- HDU 5828 Rikka with Sequence 线段树优化
- hdu5828 Rikka with Sequence(线段树)
- HDU 5828 Rikka with Sequence
- Hdu 5828 Rikka with Sequence
- HDU 5828 Rikka with Sequence
- HDU 5828 多校第八场 1008 Rikka with Sequence(线段树--数据加强版)
- 2016多校8 HDU 5828 Rikka with Sequence 线段树优化
- HDU 5828-H - Rikka with Sequence-线段树+玄学-区间开方/区间更新/区间求和
- 【HDU5828】Rikka with Sequence(线段树)
- HDU 5828 Rikka with Sequence 解题报告
- 拆分字符串 去掉字符串空格
- BRIEF 特征描述子
- 程序员面试金典目录
- java中线程安全的集合
- Android学习第十一天--------Android App AllowBackup
- 【HDU 5828】Rikka with Sequence(线段树)
- 51node-1627 瞬间移动
- php学习06-02
- 工作随笔
- ThinkPad T450无线网络不可用解决笔记
- PL/SQL如何调试Oracle存储过程
- 动态数据源3之动态分库反思
- Hadoop集群之Hive安装配置
- spring boot实战一