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. Java实现拖拽上传

    原文:http://www.open-open.com/code/view/1437358795584 在项目开发中由于实际需求,需要开发拖拽上传的功能,ok! 先看效果图: jsp上传前端代码: & ...

  2. Apache 处理svg工具包Apache(tm) Batik SVG Toolkit

    Apache™ Batik SVG Toolkit¶ Overview¶ Batik is a Java-based toolkit for applications or applets that ...

  3. 【独立开发人员er Cocos2d-x实战 008】BMFont生成位图字体工具和Cocos2dx使用载入fnt文件

    1.首先我们须要下载而且安装BMFont工具,下载地址例如以下:http://download.csdn.net/detail/chenqiai0/8899353(里面还有具体的使用文档,假设使用中有 ...

  4. vue-cli3取掉eslint格式提示报错

    把package.json文件中关于eslint那个直接去掉. "@vue/cli-plugin-eslint": "^3.7.0",

  5. 【转载】HTTP POST GET SOAP本质区别详解

    一 原理区别 一般在浏览器中输入网址访问资源都是通过GET方式:在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认为GET提交 Http定义了与服务器交互的不同方法,最基本的 ...

  6. 识别IE11浏览器

    现在俺们做的系统十分高大上,用IE的话非要上IE11或以上版本. 咋检测呢?检测到用户用IE.且IE低于IE11的话就提示他升级浏览器呢?可以酱紫: var _IE = (function (d, w ...

  7. 为Windows Live Writer添加Code插件

    1.插件效果展示 1: void CDemoDlg::OnBnClickedNmdlg() 2: { 3: CNonModeDlg *pDlg = new CNonModeDlg();// 创建一个C ...

  8. Koa2学习(五)中间件

    Koa2学习(五)中间件 Koa2通过app.use(function)方法来注册中间件. 所有的http请求都会依次调用app.use()方法,所以中间件的使用顺序非常重要. 中间件的执行顺序 官方 ...

  9. 在Android用ZXing.jar识别二维码的精简版(简化了配置和代码)

            近期公司做了一款OTP令牌激活的产品,因为之前激活手机令牌须要输入非常多的激活信息才干进行激活. 经过一段使用后,发现易用性不是非常强,考虑假设添加二维码的的扫码功能岂不是大大添加了易 ...

  10. 设计模式-(18)命令模式 (swift版)

    一,概念: 在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”.但在某些场合,比如要对行为进行“记录.撤销/重做.事务”等处理,这种无法抵御变化的紧耦合是不合适的.在这种情况下,如何将 ...