CF558E-A Simple Task-线段树+计数排序

计数排序的原理,只要知道了有几个数比i小,就可以知道i的位置

这道题只有26个字母,搞26颗线段树,然后区间更新

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4
  5 //using namespace std;
  6 const int maxn = 1e5+10;
  7
  8 int N,Q;
  9 char line[maxn];
 10
 11 #define lson rt<<1,l,mid
 12 #define rson rt<<1|1,mid+1,r
 13 #define root 1,1,N
 14
 15 struct SegrTree{
 16     int num[maxn<<2];
 17     int lazy[maxn<<2];
 18     void init()
 19     {
 20         memset(lazy,-1,sizeof lazy);
 21     }
 22     void push_up(int rt)
 23     {
 24         num[rt] = num[rt<<1] + num[rt<<1|1];
 25     }
 26     void push_down(int rt,int m)
 27     {
 28         if(lazy[rt] != -1)
 29         {
 30             num[rt<<1] = (m-(m>>1))*lazy[rt] ;
 31             num[rt<<1|1] = (m>>1)*lazy[rt] ;
 32             lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
 33             lazy[rt] = -1;
 34         }
 35     }
 36     void build(int kind,int rt,int l,int r)
 37     {
 38         if(l == r)
 39         {
 40             num[rt] = line[l-1]==kind+‘a‘;
 41             //if(line[l-1]==‘c‘) printf("%c pos:%d \n",kind+‘a‘,l);
 42             return ;
 43         }
 44         int mid = (l+r)>>1;
 45         build(kind,lson);
 46         build(kind,rson);
 47         push_up(rt);
 48     }
 49     void update(int L,int R,int d,int rt,int l,int r)
 50     {
 51         if(L <= l && R >= r)
 52         {
 53             num[rt] = (r-l+1)*d;
 54             lazy[rt] = d;
 55             return ;
 56         }
 57         push_down(rt,r-l+1);
 58         int mid = (l+r)>>1;
 59         if(L <= mid) update(L,R,d,lson);
 60         if(R >  mid) update(L,R,d,rson);
 61         push_up(rt);
 62     }
 63     int query(int L,int R,int rt,int l,int r)
 64     {
 65         if(L <= l && R >= r)
 66         {
 67             return num[rt];
 68         }
 69         push_down(rt,r-l+1);
 70         int mid = (l+r)>>1;
 71         int res = 0;
 72
 73         if(R <= mid) res = query(L,R,lson);
 74         else if(L > mid) res = query(L,R,rson);
 75         else res = query(L,R,lson)+query(L,R,rson);
 76
 77         push_up(rt);
 78         return res;
 79     }
 80 }alpha[26];
 81
 82 void sort(int l,int r,int k)
 83 {
 84     int pos,cnt;
 85     if(k == 1)
 86     {
 87         pos = l;
 88         for(int i=0;i<26;i++)
 89         {
 90             cnt = alpha[i].query(l,r,root);
 91             //printf("[%d,%d]%c k:%d pos:%d cnt:%d\n",l,r,i+‘a‘,k,pos,cnt);
 92             if(cnt)
 93             {
 94                 alpha[i].update(l,r,0,root);
 95                 alpha[i].update(pos,pos+cnt-1,1,root);
 96                 pos += cnt;
 97             }
 98         }
 99     }
100     else
101     {
102         pos = l;
103         for(int i=25;i>=0;i--)
104         {
105             cnt = alpha[i].query(l,r,root);
106             //printf("[%d,%d] %c k:%d pos:%d cnt:%d\n",l,r,i+‘a‘,k,pos,cnt);
107             if(cnt)
108             {
109                 alpha[i].update(l,r,0,root);
110                 alpha[i].update(pos,pos+cnt-1,1,root);
111                 pos += cnt;
112             }
113         }
114     }
115 }
116
117 int main()
118 {
119     //freopen("input.txt","r",stdin);
120
121     scanf("%d%d",&N,&Q);
122     scanf("%s",line);
123
124     for(int i=0;i<26;i++)
125     {
126         alpha[i].init();
127         alpha[i].build(i,root);
128         //printf("tot num:%c %d\n",i+‘a‘,alpha[i].query(1,N,root));
129     }
130     //printf("c:%d c:%d\n",alpha[2].query(1,N,root),alpha[2].query(7,10,root));
131     for(int i=0,l,r,k;i<Q;i++)
132     {
133         scanf("%d%d%d",&l,&r,&k);
134         sort(l,r,k);
135     }
136     for(int i=1;i<=N;i++)
137     {
138         for(int j=0;j<26;j++) if(alpha[j].query(i,i,root))
139         {
140             printf("%c",‘a‘+j);
141         }
142     }
143     puts("");
144 }
时间: 2024-08-08 13:53:24

CF558E-A Simple Task-线段树+计数排序的相关文章

CF558E A Simple Task 线段树

题意翻译 题目大意: 给定一个长度不超过10^5的字符串(小写英文字母),和不超过50000个操作. 每个操作 L R K 表示给区间[L,R]的字符串排序,K=1为升序,K=0为降序. 最后输出最终的字符串. 给每个数字开一个线段树    如果该数字在pos位置  那么在该数字的线段树的pos 位置+1  (有一点类似权值线段树) 因为一个点不是0就是1  (不可能有两个数字在一个点)开绝对标记即可 每次操作的时候  如果是递增的从小到大遍历数字的线段树即可  每次先找出区间个数  放在最左边

CF558E - A Simple Task线段树

给出一个小写字母组成的字符串,然后q个操作,a,b,c ,c为0 ,将区间 [a,b] 按逆字典序排,c为1,将此区间按字典序排.用一颗线段树,维护每个节点各个字母出现的种类数,每次操作操作后,暴力将字母a组成的区间,字母b组成的区间等等,区间内所有元素更新为a,b,等等.打个lazy标记,区间更新搞下就行了. #pragma comment(linker,"/STACK:102400000,102400000") #define _CRT_SECURE_NO_WARNINGS #in

codeforces 558E A Simple Task 线段树

题目链接 题意较为简单. 思路: 由于仅仅有26个字母,所以用26棵线段树维护就好了,比較easy. #include <iostream> #include <string> #include <vector> #include <cstring> #include <cstdio> #include <map> #include <queue> #include <algorithm> #include &

bzoj 3832: [Poi2014]Rally(线段树+拓扑排序)

3832: [Poi2014]Rally Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge Submit: 113  Solved: 56 [Submit][Status][Discuss] Description An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long distance cyclis

HDU 3974 Assign the task(线段树)

描述There is a company that has N employees(numbered from 1 to N),every employee in the company has a immediate boss (except for the leader of whole company).If you are the immediate boss of someone,that person is your subordinate, and all his subordin

CF558E A Simple Task

题目大意: 给定一个长度不超过10^5的字符串(小写英文字母),和不超过5000个操作. 每个操作 L R K 表示给区间[L,R]的字符串排序,K=1为升序,K=0为降序. 最后输出最终的字符串 首先这么想想,对于一段区间的排序,排完序的样子和排序之前每个字母的位置并没有关系,而是和每一个字母出现的次数有关.所以我们对于每一次操作,统计出区间中每一个字母出现了多少次,然后按字典序排序就行.更确切的说,就是这个区间中的哪一个部分都改成某一个字母,区间修改. 既然是区间修改,那么就可以用线段树实现

HDU5638 / BestCoder Round #74 (div.1) 1003 Toposort 线段树+拓扑排序

Toposort 问题描述 给出nn个点mm条边的有向无环图. 要求删掉恰好kk条边使得字典序最小的拓扑序列尽可能小. 输入描述 输入包含多组数据. 第一行有一个整数TT, 表示测试数据组数. 对于每组数据: 第一行包含3个整数nn, mm和kk (1 \le n \le 100000, 0 \le k \le m \le 200000)(1≤n≤100000,0≤k≤m≤200000), 表示图中结点数目, 图中边的数目以及要删的边数. 接下来mm行, 每行包含两个整数u_iu?i?? and

hdu 5195 DZY Loves Topological Sorting 线段树+拓扑排序

DZY Loves Topological Sorting Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5195 Description A topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for ev

hdu5195 DZY Loves Topological Sorting 线段树+拓扑排序

要求在一个DAG中删去不多于k条边,使得拓扑序的字典序最大. 贪心策略:每次删去入度小于res的,序号尽量大的点的入边. 需要用线段树维护区间最小值. 代码: #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<vector> using name