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. jmete命令行停止失败的原因分析

    1.在jmeter的master机器上使用如下方式启动远程IP地址2.2.2.2,3.3.3.3上的jmeter slave服务,执行到最后生成报告: sh apache-jmeter-3.1/bin ...

  2. 基于unicorn-engine的虚拟机的实现(WxSpectre)

    反病毒虚拟机是一个很有优势的工具,可以说反病毒软件是否存在模拟器是衡量反病毒软件能力的一个指标.反病毒虚拟机不光是内嵌在反病毒软件内部,来动态执行样本.这种虚拟机一般也可以单独用来动态执行批量样本,检 ...

  3. Office EXCEL 如何实现在单元格内换行

    按A/T+回车可以实现手动换行      

  4. protobuf 之 MessageLite 接口摘录

    class LIBPROTOBUF_EXPORT MessageLite { public: inline MessageLite() {} virtual ~MessageLite(); // Ba ...

  5. java读取Excel表格中的数据

    1.需求 用java代码读取hello.xls表格中的数据 2.hello.xls表格 3.java代码 package com.test; import java.io.File; import j ...

  6. tunctl和虚拟网卡

    1 tun/tap驱动 1.1 网卡驱动 同tcp/ip协议栈打交道,接受和发送数据包 1.2 字符驱动 内核和用户态通过字符设备交换数据包. 2 tun虚拟网卡的创建 tunctl -t tun0 ...

  7. ABAP ODATA接口开发

    1.SE37 创建好 Remote-Enabled函数. 2.SEGW,新建项目 创建项目之后,展开,右键Data Model,Import 函数. 导入函数之后,创建mapping 3./IWFND ...

  8. 设计模式-(14)装饰者模式 (swift版)

    一,概念 装饰者模式(Decorator):动态地为一个对象添加一些额外的职责,若要扩展一个对象的功能,装饰者提供了比继承更有弹性的替代方案. 多组合,少继承 二,UML图 抽象构件类(Compone ...

  9. Get started with Sourcetree

    Understand the interface Bookmarks window From that window, select the Local or Remote buttons to vi ...

  10. 四:多线程--NSOperation简单介绍

    一.NSOperation简介 1.NSOperation的作⽤:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQu ...