校赛F 比比谁更快(线段树)
http://acm.cug.edu.cn/JudgeOnline/problem.php?cid=1153&pid=5
题意:给你一个字符串,各两个操作:
ch=0,[l,r]降序
ch=1,[l,r]升序
如果是newer的话,应该会想用暴力,直接对区间sort,但是很明显是超时的(校赛怎么会这么简单呢!)
很容易想到线段数,对于线段数,我们可以先理清一下知识点,线段树大概有三种操作:
- 单点更新
- 区间更新
- RMQ
显然这里要用区间更新的操作。
区间更新有三大操作:
build()建树
update()更新
query()求和
sum[4*N]存储线段数节点
但是一般的区间更新的线段数是区间加或者区间减等统一的操作,所以对于区间排序需要对区间查询模板更改一下。
sum[4*N][26]来存储线段数节点
setv[4*N]来存储当前区间覆盖的字母
cnt[26]表示每个字母在当前区间出现的次数
下面以样例“abacdabcda”为例进行阐述:
首先是建树过程:
这一部分计算出sum[4N][26]和setv[4N]的值
其次,对于每一个查询,“l,r,ch”
都要用query(int rt,int L,int R,int l,int r,int i)计算[l,r]区间cnt[i]的值。
最后一步,对于每一个查询”l,r,ch”
根据ch的值:
做update(int rt,int L,int R,int l,int r,int i)
如果ch=0,对[l,r]降序
做法是:对cnt[i]数组从25->0 遍历,若cnt[i]>0,表示这个字符存在,且个数为cnt[i]个
所以要把[l,l+cnt[i]]个位置都要修改为cnt[i]对应的字母,并把l(当前位置后移cnt[i]位)
如果ch=1,对[l,r]升序
做法相同,只是从[0->25]遍历。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls,L,M
#define rson rs,M+1,R
using namespace std;
typedef long long ll;
const int N = 100005;
const int sigma = 26;
int sumv[N<<2][sigma], setv[N<<2]; //setv表示当前区间被覆盖的字母
int cnt[26]; //每个坐标在当前区间出现的次数
char str[N];
void pushUp(int o) {
for(int i = 0; i < sigma; i++) {
sumv[o][i] = sumv[ls][i] + sumv[rs][i];
}
}
void initNode(int o) {
memset(sumv[o], 0, sizeof(sumv[o]));
}
void pushDown(int o, int L, int R) {
int M = (L+R)/2;
if(setv[o] != -1) {
setv[ls] = setv[rs] = setv[o];
initNode(ls);
sumv[ls][setv[o]] = (M-L+1);
initNode(rs);
sumv[rs][setv[o]] = (R-M);
setv[o] = -1;
}
}
void build(int o, int L, int R) {
if(L == R) {
initNode(o);
sumv[o][str[L]-'a'] = 1;
setv[o] = str[L]-'a';
return ;
}
setv[o] = -1;
int M = (L+R)/2;
build(lson);
build(rson);
pushUp(o);
}
int query(int o, int L, int R, int ql, int qr, int val) {
if(ql <= L && R <= qr)
return sumv[o][val];
pushDown(o, L, R);
int M = (L+R)/2, ret = 0;
if(ql <= M) ret += query(lson, ql, qr, val);
if(qr > M) ret += query(rson, ql, qr, val);
return ret;
}
void modify(int o, int L, int R, int ql, int qr, int val) {
if(ql <= L && R <= qr) {
for(int i = 0; i < sigma; i++)
sumv[o][i] = 0;
setv[o] = val;
sumv[o][setv[o]] = (R-L+1);
return ;
}
pushDown(o, L, R);
int M = (L+R)/2;
if(ql <= M) modify(lson, ql, qr, val);
if(qr > M) modify(rson, ql, qr, val);
pushUp(o);
}
void getStr(int o, int L, int R) {
if(L == R) {
printf("%c", (char)('a'+setv[o]));
return ;
}
pushDown(o, L, R);
int M = (L+R)/2;
getStr(lson);
getStr(rson);
}
int n, q;
int main() {
while(scanf("%d%d", &n, &q) != EOF) {
scanf("%s", str+1);
build(1, 1, n);
int ql, qr, ch;
while(q--) {
scanf("%d%d%d", &ql, &qr, &ch);
for(int i = 0; i < sigma; i++)
cnt[i] = query(1, 1, n, ql, qr, i);
int pos = ql;
if(ch == 1) {
for(int i = 0; i < sigma; i++) {
if(cnt[i] > 0)
modify(1, 1, n, pos, pos+cnt[i]-1, i);
pos += cnt[i];
}
}else {
for(int i = sigma-1; i >= 0; i--) {
if(cnt[i] > 0)
modify(1, 1, n, pos, pos+cnt[i]-1, i);
pos += cnt[i];
}
}
}
getStr(1, 1, n); puts("");
}
return 0;
}
校赛F 比比谁更快(线段树)的更多相关文章
- hpu校赛--雪人的高度(离散化线段树)
1721: 感恩节KK专场——雪人的高度 时间限制: 1 Sec 内存限制: 128 MB 提交: 81 解决: 35 [提交][状态][讨论版] 题目描述 大雪过后,KK决定在春秋大道的某些区间 ...
- 北邮校赛 F. Gabriel's Pocket Money(树状数组)
F. Gabriel's Pocket Money 2017- BUPT Collegiate Programming Contest - sync 时间限制 2000 ms 内存限制 65536 K ...
- 牛客多校第四场sequence C (线段树+单调栈)
牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...
- 校赛F
问题描述 例如对于数列[1 2 3 4 5 6],排序后变为[6 1 5 2 4 3].换句话说,对于一个有序递增的序列a1, a2, a3, ……, an,排序后为an, a1, an-1, a2, ...
- [NOIP10.6模拟赛]2.equation题解--DFS序+线段树
题目链接: 咕 闲扯: 终于在集训中敲出正解(虽然与正解不完全相同),开心QAQ 首先比较巧,这题是\(Ebola\)出的一场模拟赛的一道题的树上强化版,当时还口胡出了那题的题解 然而考场上只得了86 ...
- HDU 4893 Wow! Such Sequence!(2014年多校联合 第三场 G)(线段树)
磨了一天的线段树,不能说完全搞清楚,只能说有一个大概的了解,靠着模板才把这道题A了,只能说太弱~~! 题意: 初始时有一字符串,全为0. 三种操作: 1 k d - add 把d加到第k个数上去2 ...
- 网络赛牡丹江赛区E ZOJ3813(线段树)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5345 给定序列P,定义序列S为P反复重复得到的一个无穷长的序列: if P = ...
- Codeforces Round #271 (Div. 2) F. Ant colony (RMQ or 线段树)
题目链接:http://codeforces.com/contest/474/problem/F 题意简而言之就是问你区间l到r之间有多少个数能整除区间内除了这个数的其他的数,然后区间长度减去数的个数 ...
- Codeforces Round #271 (Div. 2) F题 Ant colony(线段树)
题目地址:http://codeforces.com/contest/474/problem/F 由题意可知,最后能够留下来的一定是区间最小gcd. 那就转化成了该区间内与区间最小gcd数相等的个数. ...
随机推荐
- 提示:“请检查浏览器代理设置”/xx-net
1.删除已导入的证书文件(运行certmgr.msc和certlm.msc,然后自己找到xxnet删),2.更新3.3.1(或是自己找到那行代码取消注释,楼下有人提及)3.删除data文件夹(下的ce ...
- LUA协程复用
-----协程复用根函数 local function routine(fun, args) while (fun) do fun, args = coroutine.yield(fun(table. ...
- swift-for循环遍历,遍历字典,循环生成数组
// Playground - noun: a place where people can play import UIKit //--------------------------------- ...
- css 滤镜之Gradient
CreateTime--2017年12月26日11:09:14 Author:Marydon ie滤镜特效之Gradient 作用: 用于设置渐变背景色 使用条件: IE9及以下版本不支持属性ba ...
- OO模式-Composite
组合模式也叫做"部分-总体"模式,这样事实上定义也就非常明显了,正好和数据结构的知识相相应.把对象组合成树形结构以表示"部分-总体"的层次结构. 先看类图: w ...
- A Simple Example About Privileged Methods in JavaScript
Douglas Crockford classified the "class methods" in JavaScript into three types: private, ...
- java语法基础(三)
类和对象 面向对象语言概述 java是一种面向对象的语言,什么是面向对象的语言? 要搞清楚什么是面向对象语言,我们需要相对的了解一下面向过程的语言. java入门阶段,我们又给大家说过一些语言的分类, ...
- Entity FramWork Code first 使用心得
1 最有用的命令 update-database -force -verbose 2 主键如果不是默认的int或者 bigint而是guid 或者 string类型,创建记录的时候要给主键赋值 3 在 ...
- eclipse 重启/打开内置浏览器
重启 Eclipse 重启选项允许用户重启 Eclipse. 我们可以通过点击 File 菜单选择 Restart 菜单项来重启 Eclipse. Eclipse 内置浏览器 Web 浏览器 Ecli ...
- POJ3616 Milking Time —— DP
题目链接:http://poj.org/problem?id=3616 Milking Time Time Limit: 1000MS Memory Limit: 65536K Total Sub ...