string 26线段树
来源:互联网 发布:中断windows更新 编辑:程序博客网 时间:2024/06/16 18:49
10.4
思路:
用线段树维护区间内a~z 的个数,每次询问拆成26 个区间修改操作。也就是说处理出一个区间a~z 的个数,然后按升序降序区间修改。常数有点大,需要卡卡。比如query的时候返回一个结构体什么的。
#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>using namespace std;const int maxn = 100010;int a[maxn], n, T, cnt[50], sum[50];char s[maxn];inline const int read(){ register int f = 1, x = 0; register char ch = getchar(); while(ch < '0' || ch > '9') ch = getchar(); while(ch >= '0' && ch <= '9') x = (x<<3) + (x<<1) + ch - '0', ch = getchar(); return x;}struct Node{ Node *ls, *rs; int cnt[27], flag; Node(){ flag = 0 ; memset( cnt , 0 , sizeof( cnt )) ;} Node operator+( const Node &a ) const{ Node tmp = Node(); for(int i=1; i<=26; ++i) tmp.cnt[i] = cnt[i] + a.cnt[i] ; return tmp; } void pushdown(int lf, int rg){ if( flag ){ int mid = (lf + rg) >> 1; ls->cnt[flag] = mid - lf + 1; ls->flag = flag; rs->cnt[flag] = rg - mid; rs->flag= flag; for(int i=1; i<=26; ++i) if(i != flag) ls->cnt[i] = rs->cnt[i] = 0; flag = 0; } } void update(){ for(int i=1; i<=26; ++i) cnt[i] = ls->cnt[i] + rs->cnt[i]; }}pool[maxn*20], *tail = pool, *rot;inline Node* build(int lf, int rg){ Node *nd = ++tail; if(lf == rg) { for(int i=1; i<=26; ++i) nd->cnt[i] = 0; nd->cnt[a[lf]]++; return nd; } int mid = (lf + rg) >> 1; nd->ls = build(lf, mid); nd->rs = build(mid+1, rg); nd->update(); return nd;}inline void modify(Node *nd, int lf, int rg, int L, int R, int data){ if(L <= lf && rg <= R){ nd->cnt[data] = rg - lf + 1; nd->flag = data; for(int i=1; i<=26; ++i) if(i != data) nd->cnt[i] = 0; return; } nd->pushdown(lf, rg); int mid = (lf + rg) >> 1; if(L <= mid) modify(nd->ls, lf, mid, L, R, data); if(R > mid) modify(nd->rs, mid+1, rg, L, R, data); nd->update(); return;}inline Node query(Node *nd, int lf, int rg , int L , int R ){ if( L <= lf && rg <= R ) return *nd; Node rt = Node() ; nd->pushdown(lf, rg) ; int mid = ( lf + rg ) >> 1 ; if( L <= mid ) rt = rt + query( nd->ls, lf , mid , L , R ) ; if( R > mid ) rt = rt + query( nd->rs, mid+1, rg , L , R ) ; return rt ;}//返回一个结构体(内有cnt[1~26]),就只需要run一次,而不是26次了。 inline int query_point(Node *nd, int lf, int rg, int pos){ if(lf == rg){ for(int i=1; i<=26; ++i) if(nd->cnt[i]) return i; } nd->pushdown(lf, rg); int mid = (lf + rg) >> 1, rt = 0; if(pos <= mid) rt = query_point(nd->ls, lf, mid, pos); else rt = query_point(nd->rs, mid+1, rg, pos); nd->update(); return rt;}int main(){ freopen("string.in", "r", stdin); freopen("string.out", "w", stdout); n = read(), T = read(); scanf("%s", s+1); for(register int i=1; i<=n; ++i) a[i] = s[i] - 'a' + 1; rot = build(1, n); for(int i=1; i<=T; ++i){ int l = read(), r = read(), opt = read(); Node t = query(rot, 1, n, l, r);//答案结构体 for(int j=1; j<=26; ++j) sum[j] = t.cnt[j]; int st = l; if( opt ){ for(int j=1; j<=26; ++j) if( sum[j] ) modify(rot, 1, n, st, st+sum[j]-1, j), st += sum[j]; } else{ for(int j=26; j>=1; --j) if( sum[j] ) modify(rot, 1, n, st, st+sum[j]-1, j), st += sum[j]; } } for(register int j=1; j<=n; ++j) printf("%c", query_point(rot, 1, n, j) + 'a' - 1); return 0;}/*5 2cabcd1 3 13 5 0*/
阅读全文
0 0
- string 26线段树
- 线段树 string
- cf_159C. String Manipulation线段树+字符串
- POJ 2887 Big String 线段树离线
- Query on a string【线段树】
- 计蒜客 Query on a string 线段树
- Query on a string 线段树
- HDU 6194 string string string 后缀数组 + RMQ(线段树)
- HDU-6096 String(字典树+线段树扫描线)
- HDU 3973 AC's String(hash+线段树)
- POJ 2887 Big String(线段树 离线处理)
- POJ 2887 Big String (线段树解法)
- CSUOJ 1942 Sort String 线段树 操作变换
- 计蒜客 Query on a string (线段树)
- HDU 6194 String String String (后缀数组+线段树, 2017 ACM/ICPC Asia Regional Shenyang Online)
- 线段树 2017.4.26
- 线段树?线段树!
- 线段树?线段树!
- uva 690 Pipeline Scheduling
- Xilinx SDK文本编辑器行号显示和背景颜色改变
- 重装macOS的基本步骤
- 安装MySQL_Python时出现is not a supported wheel on this platform.
- poj 1986 Distance Queries 离线LCA
- string 26线段树
- 运输层TCP协议
- 【学术篇】luogu2184贪婪大陆
- Flask-SQLAlchemy增删改查
- “面向对象”和“面向过程”的区别
- 简单分组
- jsp初识
- Dsp F2812 实验报告[南京理工]
- OPenCV3.2 图像反差的两种方法