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 比比谁更快(线段树)的更多相关文章

  1. hpu校赛--雪人的高度(离散化线段树)

    1721: 感恩节KK专场——雪人的高度 时间限制: 1 Sec  内存限制: 128 MB 提交: 81  解决: 35 [提交][状态][讨论版] 题目描述 大雪过后,KK决定在春秋大道的某些区间 ...

  2. 北邮校赛 F. Gabriel's Pocket Money(树状数组)

    F. Gabriel's Pocket Money 2017- BUPT Collegiate Programming Contest - sync 时间限制 2000 ms 内存限制 65536 K ...

  3. 牛客多校第四场sequence C (线段树+单调栈)

    牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...

  4. 校赛F

    问题描述 例如对于数列[1 2 3 4 5 6],排序后变为[6 1 5 2 4 3].换句话说,对于一个有序递增的序列a1, a2, a3, ……, an,排序后为an, a1, an-1, a2, ...

  5. [NOIP10.6模拟赛]2.equation题解--DFS序+线段树

    题目链接: 咕 闲扯: 终于在集训中敲出正解(虽然与正解不完全相同),开心QAQ 首先比较巧,这题是\(Ebola\)出的一场模拟赛的一道题的树上强化版,当时还口胡出了那题的题解 然而考场上只得了86 ...

  6. HDU 4893 Wow! Such Sequence!(2014年多校联合 第三场 G)(线段树)

    磨了一天的线段树,不能说完全搞清楚,只能说有一个大概的了解,靠着模板才把这道题A了,只能说太弱~~! 题意: 初始时有一字符串,全为0. 三种操作: 1 k d - add  把d加到第k个数上去2 ...

  7. 网络赛牡丹江赛区E ZOJ3813(线段树)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5345 给定序列P,定义序列S为P反复重复得到的一个无穷长的序列: if P = ...

  8. Codeforces Round #271 (Div. 2) F. Ant colony (RMQ or 线段树)

    题目链接:http://codeforces.com/contest/474/problem/F 题意简而言之就是问你区间l到r之间有多少个数能整除区间内除了这个数的其他的数,然后区间长度减去数的个数 ...

  9. Codeforces Round #271 (Div. 2) F题 Ant colony(线段树)

    题目地址:http://codeforces.com/contest/474/problem/F 由题意可知,最后能够留下来的一定是区间最小gcd. 那就转化成了该区间内与区间最小gcd数相等的个数. ...

随机推荐

  1. guava缓存设置return null一直报错空指针

    guava缓存设置return null一直报错空指针 因为缓存不允许返回为空

  2. datatable使用介绍

    Datatables是一款jquery表格插件.它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能. 1.支持分页:前台分页和后台分页 前台分页:后台一次把数据传过来,交给前端渲染.缺点 ...

  3. 【Nginx】Nginx事件模块

    一.事件处理框架概述 事件处理框架所要解决的问题是如何收集.管理.分发事件.事件以网络事件和定时器事件为主,而网络事件中以TCP网络事件为主.事件处理框架需要在不同的操作系统内核中选择一种事件驱动机制 ...

  4. 使用Android SwipeRefreshLayout了解Android的嵌套滑动机制

    SwipeRefreshLayout 是在Android Support Library, revision 19.1.0加入到support v4库中的一个下拉刷新控件,关于android的下拉刷新 ...

  5. jquery 动态添加,降低input表单的方法

    html代码例如以下 <html> <tr><button style="margin-left:10px" class="add_fiel ...

  6. The data property "dialogVisble" is already declared as a prop. Use prop default value instead报错原因

    vue中使用props传递数据就不能在子组件的data中用同样的名字(比如dialogVisble)了,否则会报错.解决方法直接去掉data中的相同名字改为其他的.

  7. Swift String 一些经常用法

    直接上代码 //字符串 //1 推断字符串是否为空 var test1Str="" var test1Str2:String = String(); println("t ...

  8. phpexcel不能输出中文

    问题描写叙述:在使用phpexcel时,假设在单元格中填充中文内容,会导致输出单元格为空的情况,甚至连中文的字符(?!等)都无法识别. 产生原因:从网上查是utf-8的问题 解决方法:能够用iconv ...

  9. 反射学习总结 --为理解SpringMVC底层做准备

    反射是什么? 通俗理解 - 照X光. java:一个类在反射面前就像照X光,清清楚楚明明白白. 应用:我们的ide中,能够"."一下就知道类中的所有方法就是通过反射实现的. XML ...

  10. linux document and directory find

    http://suchalin.blog.163.com/blog/static/55304677201062924959497/ Linux 查看文件夹大小及文件数量命令 2010-07-29 14 ...