HDU 5828 Rikka with Sequence (线段树)
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;
if(left==right){
tree[i].sum = num[left];
tree[i].equl = num[left];
return ;
}
int mid=mid(left,right);
build(i<<1,left,mid);
build(i<<1|1,mid+1,right);
tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
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 ;
}
pushdown(i);
int mid=mid(tree[i].left,tree[i].right);
if(right<=mid) update(i<<1,left,right,d);
else if(left>mid) update(i<<1|1,left,right,d);
else {
update(i<<1,left,mid,d);
update(i<<1|1,mid+1,right,d);
}
tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
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 ;
}
pushdown(i);
int mid=mid(tree[i].left,tree[i].right);
if(right<=mid) update_sqrt(i<<1,left,right);
else if(left>mid) update_sqrt(i<<1|1,left,right);
else {
update_sqrt(i<<1,left,mid);
update_sqrt(i<<1|1,mid+1,right);
}
tree[i].sum = tree[i<<1].sum + tree[i<<1|1].sum;
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;
pushdown(i);
int mid=mid(tree[i].left,tree[i].right);
if(right<=mid) return query(i<<1,left,right);
else if(left>mid) return query(i<<1|1,left,right);
else return query(i<<1,left,mid)+query(i<<1|1,mid+1,right);
}
int main(int argc, char const *argv[])
{
//IN;
int t; cin >> t;
while(t--)
{
int m;
scanf("%d %d", &n,&m);
for(int i=1; i<=n; i++)
scanf("%lld", &num[i]);
build(1, 1, n);
while(m--) {
int op, l, r;
scanf("%d %d %d", &op,&l,&r);
if(op == 1) {
LL x; scanf("%lld", &x);
update(1, l, r, x);
}
else if(op == 2) {
update_sqrt(1, l, r);
}
else if(op == 3) {
printf("%lld\n", query(1, l, r));
}
}
}
return 0;
}
HDU 5828 Rikka with Sequence (线段树)的更多相关文章
- hdu 5828 Rikka with Sequence 线段树
Rikka with Sequence 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5828 Description As we know, Rik ...
- HDU 5828 Rikka with Sequence (线段树+剪枝优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5828 给你n个数,三种操作.操作1是将l到r之间的数都加上x:操作2是将l到r之间的数都开方:操作3是 ...
- HDU 5828 Rikka with Sequence(线段树区间加开根求和)
Problem DescriptionAs we know, Rikka is poor at math. Yuta is worrying about this situation, so he g ...
- 2016暑假多校联合---Rikka with Sequence (线段树)
2016暑假多校联合---Rikka with Sequence (线段树) Problem Description As we know, Rikka is poor at math. Yuta i ...
- 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence
// 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...
- HDU 5828 Rikka with Sequence(线段树 开根号)
Rikka with Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- 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区间上的所以数变成 ...
- HDU 6089 Rikka with Terrorist (线段树)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6089 题解 这波强行维护搞得我很懵逼... 扫描线,只考虑每个点能走到左上方(不包括正上方,但包括正左 ...
- HDU 5634 Rikka with Phi 线段树
题意:bc round 73 div1 D 中文题面 分析:注意到10^7之内的数最多phi O(log(n))次就会变成1, 因此可以考虑把一段相同的不为1的数缩成一个点,用平衡树来维护. 每次求p ...
随机推荐
- Android开发之创建App Widget和更新Widget内容
App WidgetsApp Widgets are miniature application views that can be embedded in other applications (s ...
- zoj 3785 What day is that day? (打表找规律)
题目 思路:比赛的时候有想过找循环节,但是,打表打错了. 后来,看着过了挺多人,就急了, 看了一下别人的时间 耗时都挺长的,就以为不是找规律, 没想到真是找规律,不过,这个题的数据可能挺大的. AC代 ...
- hdu 2372 El Dorado (dp)
题目链接 题意:给n个数字, 求有k个数字的上升子序列有多少种. 思路:d[i][j]表示 以第i个元素为 子序列的最后一个元素,长度为j的子序列 有多少种. 比赛的时候 光想着用组合数做了..... ...
- Struts2系列——struts2的result
在action的指定方法执行完毕后总会返回一个字符串,struts2根据返回的字符串去action的配置中的result去找匹配的名字,根据配置执行下一步的操作. 在ActionSupport基类中定 ...
- Codeforces 379D - New Year Letter
原题地址:http://codeforces.com/contest/379/problem/D 题目大意:给出一种生成字符串的方法 s[k] = s[k - 2] + s[k - 1],其中加法意为 ...
- BootStrap基本样式
文本对齐风格:.text-left:左对齐.text-center:居中对齐.text-right:右对齐.text-justify:两端对齐 取消列表符号:.list-unstyled内联列表:.l ...
- LA 3266 (贪心) Tian Ji -- The Horse Racing
题意: 田忌和齐王各有n匹马,如果马的速度比齐王的快就赢200,慢则输200,相等不赔不赚. 已知两人每匹马的速度(为整数)和齐王所排出的马的顺序,问田忌该如何应对才能使收益最大. 分析: 本以为是一 ...
- java 访问器方法中对象引用的问题
"注意不要编写返回引用可变对象的访问器方法".因为会破坏类的封装性,引用的内容可能会被改变,产生业务逻辑上的错误. 什么是可变对象? 先要搞清楚java中值传递和引用传递的问题,总结如下: 1.对象就 ...
- MySQL基础之第7章 索引
第7章 索引 MySQL中,所有的数据类型都可以被索引,包括普通索引,唯一性索引,全文索引,单列索引,多列索引和空间索引等. 7.1.索引简介 7.1.1.索引的含义和特点 BTREE索引,HASH索 ...
- IO负载高的来源定位
前言: 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(iostat中的util),但是无法快速的定位到IO负载的来源进程和来源文件导致无法进行相应的策略来解决问题. 这个现象在MySQ ...