Q - Play With Sequence HDU - 3971 线段树 重新排序建树
Q - Play With Sequence
这个题目是一个线段树,比较特别的线段树,就是c询问一定次数之后重新排序建树来优化减低复杂度。
第一次碰到这种题目有点迷。
这个题目写还是很好写的,就是重新排序建树的位置不太好找。
不过可以知道的是,这是更新花费时间和排序花费时间的一个平衡,这个是一个二次函数,这个二次函数的最低点可以自己测出来。
现在可能有点听不懂,写完代码就很好理解了,
我测的每隔2000次C的操作就重新建树排序是最优的。
800,1000,2200,3000 都是可以的。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
#include <string>
#include <vector>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = 3e5 + ;
typedef long long ll;
ll a[maxn], lc[maxn], rc[maxn], num[maxn];
string s[maxn];
struct node
{
ll lazy, max, min, len;
}tree[maxn*];
void push_up(int id)
{
tree[id].max = max(tree[id << ].max, tree[id << | ].max);
tree[id].min = min(tree[id << ].min, tree[id << | ].min);
//printf("tree[%d].min=%lld tree[%d].max=%lld\n", id, tree[id].min, id, tree[id].max);
} void build(int id,int l,int r)
{
tree[id].len = r - l + ;
tree[id].lazy = ;
if(l==r)
{
tree[id].max = tree[id].min = a[l];
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
push_up(id);
} void push_down(int id)
{
if(tree[id].lazy)
{
int val = tree[id].lazy;
tree[id << ].max += val;
tree[id << ].min += val;
tree[id << | ].max += val;
tree[id << | ].min += val;
tree[id << ].lazy += val;
tree[id << | ].lazy += val;
// printf("tree[%d].max=%lld tree[%d].min=%lld\n", id << 1, tree[id << 1].max, id << 1, tree[id << 1].min);
// printf("tree[%d].max=%lld tree[%d].min=%lld\n", id << 1 | 1, tree[id << 1 | 1].max, id << 1 | 1, tree[id << 1 | 1].min);
tree[id].lazy = ;
}
}
void update(int id,int l,int r,ll x,ll y,ll val)
{
push_down(id);
// printf("id=%d l=%d r=%d x=%lld y=%lld val=%lld\n", id, l, r, x, y, val);
if(tree[id].min>=x&&tree[id].max<=y)
{
tree[id].lazy = val;
tree[id].min += val;
tree[id].max += val;
//printf("id=%d min=%lld max=%lld\n", id, tree[id].min, tree[id].max);
return;
}
int mid = (l + r) >> ;
if (tree[id << ].max >= x && tree[id << ].min <= y) update(id << , l, mid, x, y, val);
if (tree[id << | ].max >= x && tree[id << | ].min <= y) update(id << | , mid + , r, x, y, val);
push_up(id);
} int query(int id,int l,int r,ll x,ll y)
{
push_down(id);
if(tree[id].max<=y&&tree[id].min>=x)
{
return tree[id].len;
}
int mid = (l + r) >> , ans = ;
if (tree[id << ].max >= x && tree[id << ].min <= y) ans += query(id << , l, mid, x, y);
if (tree[id << | ].max >= x && tree[id << | ].min <= y) ans += query(id << | , mid + , r, x, y);
return ans;
} void push_alldown(int id,int l,int r)
{
if(l==r)
{
a[l] = tree[id].max;
return;
}
push_down(id);
int mid = (l + r) >> ;
push_alldown(id << , l, mid);
push_alldown(id << | , mid + , r);
} int main()
{
int n, m;
while(scanf("%d%d",&n,&m)!=EOF)
{
for (int i = ; i <= n; i++) scanf("%lld", &a[i]);
sort(a + , a + + n);
build(, , n);
int cnt = ;
for(int i=;i<=m;i++)
{
cin >> s[i];
if (s[i] == "C") scanf("%lld%lld%lld", &lc[i], &rc[i], &num[i]), cnt++;
else scanf("%lld%lld", &lc[i], &rc[i]), num[i] = ;
}
int tot = ;
for(int i=;i<=m;i++)
{
if(s[i]=="C")
{
++tot;
//push_alldown(1, 1, n);
//printf("lc[%d]=%lld rc[%d]=%lld num[%d]=%lld\n", i, lc[i], i, rc[i], i, num[i]);
update(, , n, lc[i], rc[i], num[i]);
if(tot%==)
{
push_alldown(, , n);
sort(a + , a + + n);
build(, , n);
}
}
else
{
int ans = query(, , n, lc[i], rc[i]);
printf("%d\n", ans);
}
}
}
}
线段树 排序建树
Q - Play With Sequence HDU - 3971 线段树 重新排序建树的更多相关文章
- hdu 3436 线段树 一顿操作
Queue-jumpers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) To ...
- hdu 3397 线段树双标记
Sequence operation Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 2871 线段树(各种操作)
Memory Control Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- hdu 4267 线段树间隔更新
A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K ...
- hdu 4747 线段树
Mex Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- hdu 3954 线段树 (标记)
Level up Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- hdu 1754 线段树(Max+单点修改)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- hdu 1166 线段树(sum+单点修改)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)
Weak Pair Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total ...
随机推荐
- 014-预处理指令-C语言笔记
014-预处理指令-C语言笔记 学习目标 1.[掌握]枚举 2.[掌握]typedef关键字 3.[理解]预处理指令 4.[掌握]#define宏定义 5.[掌握]条件编译 6.[掌握]static与 ...
- MyEclipse 10安装SVN插件subclipse
1. 下载SVN插件subclipse 下载地址:http://subclipse.tigris.org/servlets/ProjectDocumentList?expandFolder=2240& ...
- 利用 Github 网络钩子实现自动化部署
GitHub 的网络钩子(webhook)功能,可以很方便的实现自动化部署.本文记录了使用 Node.js 的开发部署过程,当项目的 master 分支被推时,将在服务器进行自动部署 添加网路钩子 在 ...
- 【three.js 第一课】创建场景,显示几何体
<!DOCTYPE html> <html> <head> <title>demo1</title> </head> <s ...
- B - Bash and a Tough Math Puzzle CodeForces - 914D (线段树的巧妙应用)
题目大意:当输入2时,将p处的点的值修改为x, 当输入1时,判断区间[L,R]的gcd是否几乎正确,几乎正确的定义是最多修改一个数,使得区间[L,R]的gcd为x. 题解:用线段树维护一个gcd数组, ...
- 多线程高并发编程(6) -- Semaphere、Exchanger源码分析
一.Semaphere 1.概念 一个计数信号量.在概念上,信号量维持一组许可证.如果有必要,每个acquire()都会阻塞,直到许可证可用,然后才能使用它.每个release()添加许可证,潜在地释 ...
- Laravel - 上手实现 - 文件上传、保存到 public 目录下
1.为了访问方便,将上传的文件保存在 public 目录下,需要进行修改配置. 找到 config/filesystems.php 文件然后修改 root.具体如下: 'local' => [ ...
- IDE使用GIT控制项目版本
IDEA本身继承GIT开发插件.只需要安装windows git客户端即可使用. check in project 检入项目 将新创建的项目上传到服务器. 对于git来说,空的目录不会上传到远程仓库. ...
- Flutter Weekly Issue 53
插件 left-scroll-actions A useful left scroll actions widget like WeChat.一款仿微信效果的 Flutter 左滑菜单插件.现在支持i ...
- 解释BOM头和去掉方法
http://www.thinkphp.cn/topic/2592.html 以上是叫你去掉bom头的,因为有些文件加载不出来就是window会以记事本的形式打开,然后默认给我们加了了bom头,有些文 ...