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;
}

posted on 2021-08-19 20:30  gryzy  阅读(83)  评论(1编辑  收藏  举报

导航