luogu2787 语文1(chin1)- 理理思维
题目描述
考试开始了,可是蒟蒻 HansBug 脑中还是一片空白。哦不!准确的说是乱七八糟的。现在首要任务就是帮蒟蒻 HansBug 理理思维。假设 HansBug 的思维是一长串字符串(字符串中包含且仅包含 26 个字母),现在的你,有一张神奇的药方,上面依次包含了三种操作:
1、 获取第 x 到第 y 个字符中字母 k 出现了多少次
2、将第 x 到第 y 个字符全部赋值为字母 k
3、将第 x 到第 y 个字符按照 \(\text{a} \sim \text{z}\) 的顺序排序
你欣喜若狂之时,可是他脑细胞和 RP 已经因为之前过度紧张消耗殆尽,眼看试卷最后还有一篇八百字的作文呢,所以这个关键的任务就交给你啦!
输入格式
第一行包含两个整数 n,m,分别表示 HansBug 的思维所包含的字母个数和药方上操作个数。 第二行包含一个长度为 n 的字符串,表示 HansBug 的思维。
接下来 m 行,每行表示一个操作,格式如下:
1 x y k 表示将第 x 到第 y 个字符中 k 出现的次数输出
2 x y k 表示将第 x 到第 y 个字符全部替换为 k
3 x y 表示将第 x 到第 y 个字符按照 \(\text{a} \sim \text{z}\) 的顺序排序
输出格式
输出为若干行,每行包含一个整数,依次为所有操作 11 所得的结果。
输入输出样例
输入
10 5
ABCDABCDCD
1 1 3 A
3 1 5
1 1 3 A
2 1 2 B
1 2 3 B
输出
1
2
2
正解就不说了,没做。
主要是练习ODT
ODT,old driver tree(老司机树)。一种线性的多个连续相同点合为一个点(当然要加上边界)并利用STL中的set进行维护的数据结构。很强很暴力!
使用要求:
- 数据随即
- 有区间赋值操作
主要操作:split、assign
其它操作:暴力就好的
注意现在有一些题目已经开始卡这个数据结构,比如这个题,后面又加了3个加强数据,过不了。P2572 [SCOI2010]序列操作,更加过份,卡成了30分。原因很简单,这个算法比较无赖!
#include<vector>
#include<cstdio>
#include<set>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<bits/stdc++.h>
#define ll long long
#define it set<node>::iterator
#define pir pair<char,int>
using namespace std;
const int maxn=5e4+10;
struct node
{
int l,r;
mutable char c;
node(int tl,int tr=-1,char tc=0):l(tl),r(tr),c(tc){}
bool operator < (const node & a)const
{
return l<a.l;
}
};
set < node > odt;
it split(int pos)
{
it p=odt.lower_bound(node(pos));
if(p!=odt.end()&&p->l==pos)return p;
--p;
int l=p->l,r=p->r;
char c=p->c;
odt.erase(p);
odt.insert(node(l,pos-1,c));
return odt.insert(node(pos,r,c)).first;
}
void assign(int l,int r,char c)
{
it pr=split(r+1),pl=split(l);
odt.erase(pl,pr);
odt.insert(node(l,r,c));
}
int countt(int l,int r,char c)
{
int ans=0;
it pr=split(r+1),pl=split(l);
for(;pl!=pr;++pl)ans+=pl->c==c?(pl->r-pl->l)+1:0;
return ans;
}
void sortt(int l,int r)
{
vector<pir>v;
it pr=split(r+1),pl=split(l);
for(it i=pl;i!=pr;++i)v.push_back(pir(i->c,i->r-i->l+1));
// for(int i=0;i<v.size();++i)cout<<v[i].first<<" "<<v[i].second<<endl;
// cout<<"____________________"<<endl;
sort(v.begin(),v.end());
// for(int i=0;i<v.size();++i)cout<<v[i].first<<" "<<v[i].second<<endl;
// cout<<"____________________"<<endl;
odt.erase(pl,pr);
for(int i=0;i<v.size();++i)
{
odt.insert(node(l,l+v[i].second-1,v[i].first));
l+=v[i].second;
}
}
int n,m;
char s[maxn];
void print()
{
for(it p=odt.begin();p!=odt.end();++p)
{
cout<<"l:"<<p->l<<" ";
cout<<"r:"<<p->r<<" ";
cout<<"c:"<<p->c<<endl;
}
}
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",s);
int nn=strlen(s);
for(int i=0;i<nn;++i)if(s[i]>='a')s[i]-=32;
for(int i=0;i<nn;++i)odt.insert(node(i+1,i+1,s[i]));
int op,l,r;
char c[3];
while(m--)
{
scanf("%d%d%d",&op,&l,&r);
if(op!=3)scanf("%s",c);
if(c[0]>='a')c[0]-=32;
if(op==1)printf("%d\n",countt(l,r,c[0]));
else if(op==2)assign(l,r,c[0]);
else sortt(l,r);
}
return 0;
}