【Ybt OJ】[数据结构 第4章] 线段树 [后半章]

45 篇文章 0 订阅
30 篇文章 0 订阅

「 「 数据结构 」 」 4 4 4章 线段树 ( ( ( 2 2 2 ) ) )
目录:

D.维护序列
E.字符串排序

大家好 我是个菜鸡 我非常喜欢暴力数据结构 于是我用线段树过了这些题(

D . D. D. 例题 4 4 4 维护序列

在这里插入图片描述
在这里插入图片描述
洛谷 l i n k 1 link1 link1 洛谷 l i n k 2 link2 link2

分析:

和例题 2 2 2差不多 就是加了个乘操作
但要注意 维护 l a z y lazy lazy标记 和下传时 先乘再加

因为 如果维护的是 a a a l a z y lazy lazy标记有 + c +c +c × b \times b ×b
但是 a × b + c ≠ ( a + c ) × b a\times b+c≠(a+c)\times b a×b+c=(a+c)×b
那维护 l a z y lazy lazy标记时 乘和加放在一起 就不知道谁先谁后了
先加后乘 : ( a + c ) × b = a × b + c × b :(a+c)\times b=a\times b+c\times b (a+c)×b=a×b+c×b
先乘后加 : a × b + c :a\times b+c a×b+c
也就是 先维护乘后加 再 × \times ×一个 b b b 就可以再维护先加后乘了

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<bitset>
#define Ctnue continue
//#pragma GCC optimize(2)
#define reg register
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int N=1e5+5;
struct Seg{
	ll sum,lazyA,lazyT;
}tree[N<<2];
int n,q,a[N],mod;
void up(int x){tree[x].sum=(tree[x<<1].sum+tree[x<<1|1].sum)%mod;}
void down(int x,int l,int r)
{
	tree[x<<1].lazyT=(tree[x<<1].lazyT*tree[x].lazyT)%mod;
	tree[x<<1].lazyA=(tree[x<<1].lazyA*tree[x].lazyT)%mod;
	tree[x<<1].sum=(tree[x<<1].sum*tree[x].lazyT)%mod;
	tree[x<<1|1].lazyT=(tree[x<<1|1].lazyT*tree[x].lazyT)%mod;
	tree[x<<1|1].lazyA=(tree[x<<1|1].lazyA*tree[x].lazyT)%mod;
	tree[x<<1|1].sum=(tree[x<<1|1].sum*tree[x].lazyT)%mod;
	tree[x].lazyT=1;int mid=(l+r)>>1;
	tree[x<<1].lazyA=(tree[x<<1].lazyA+tree[x].lazyA)%mod;
	tree[x<<1].sum=(tree[x<<1].sum+tree[x].lazyA*(mid-l+1)%mod)%mod;
	tree[x<<1|1].lazyA=(tree[x<<1|1].lazyA+tree[x].lazyA)%mod;
	tree[x<<1|1].sum=(tree[x<<1|1].sum+tree[x].lazyA*(r-(mid+1)+1)%mod)%mod;
	tree[x].lazyA=0;
}
void build(int x,int l,int r)
{
	tree[x].lazyT=1;
	if(l==r){
		tree[x].sum=a[l]%mod;
		return;
	}
	int mid=(l+r)>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	up(x);
}
void times(int x,int l,int r,int L,int R,int value)
{
	if(L<=l&&r<=R)
	{
		tree[x].sum=(tree[x].sum*value)%mod;
		tree[x].lazyA=(tree[x].lazyA*value)%mod;
		tree[x].lazyT=(tree[x].lazyT*value)%mod;
		return;
	}
	down(x,l,r);
	int mid=(l+r)>>1;
	if(L<=mid) times(x<<1,l,mid,L,R,value);
	if(mid<R) times(x<<1|1,mid+1,r,L,R,value);
	up(x);
}
void add(int x,int l,int r,int L,int R,int value)
{
	if(L<=l&&r<=R)
	{
		tree[x].sum=(tree[x].sum+value*(r-l+1)%mod)%mod;
		tree[x].lazyA=(tree[x].lazyA+value)%mod;
		return;
	}
	down(x,l,r);
	int mid=(l+r)>>1;
	if(L<=mid) add(x<<1,l,mid,L,R,value);
	if(mid<R) add(x<<1|1,mid+1,r,L,R,value);
	up(x);
}
ll query(int x,int l,int r,int L,int R)
{
	if(L<=l&&r<=R) return tree[x].sum;
	down(x,l,r);
	int mid=(l+r)>>1;
	ll ans=0;
	if(L<=mid) ans=(ans+query(x<<1,l,mid,L,R))%mod;
	if(mid<R) ans=(ans+query(x<<1|1,mid+1,r,L,R))%mod;
	return ans;
}
int main()
{
	scanf("%d%d",&n,&mod);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	build(1,1,n);
	scanf("%d",&q);
	while(q--)
	{
		int kd,x,y,val;
		scanf("%d",&kd);
		if(kd==1)
		{
			scanf("%d%d%d",&x,&y,&val);
			times(1,1,n,x,y,val);
		}
		if(kd==2){
			scanf("%d%d%d",&x,&y,&val);
			add(1,1,n,x,y,val);
		}
		if(kd==3){
			scanf("%d%d",&x,&y);
			printf("%lld\n",query(1,1,n,x,y));
		}
	}
	
	
	return 0;
} 

E . E. E. 例题 5 5 5 字符串排序

在这里插入图片描述
L u o g u Luogu Luogu l i n k link link

分析:

线段树
每个叶子节点就是对应字符的值
维护区间 [ l , r ] [l,r] [l,r] 中各个字符的次数
然后 分别按升序降序 依次替换线段树中的位置

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<bitset>
#define Ctnue continue
//#pragma GCC optimize(2)
#define reg register
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int N=1e5+5;
struct node{
	int l,r,val;
}tree[N<<2];
char s[N];
int n,m,len[27];
void build(int x,int l,int r)
{
	tree[x].l=l;tree[x].r=r;
	if(l==r){
		tree[x].val=s[l]-'a'+1;
		return;
	}
	int mid=(l+r)>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
	if(tree[x<<1].val==tree[x<<1|1].val) tree[x].val=tree[x<<1].val;
} 
void update(int x,int l,int r)
{
	if(l<=tree[x].l&&tree[x].r<=r&&tree[x].val!=0)
	{
		len[tree[x].val]+=tree[x].r-tree[x].l+1;
		return;
	} 
	if(tree[x].val){
		tree[x<<1].val=tree[x].val;
		tree[x<<1|1].val=tree[x].val;
	}
	int mid=(tree[x].l+tree[x].r)>>1;
	if(l<=mid) update(x<<1,l,r);
	if(mid<r) update(x<<1|1,l,r);
}
void query(int x,int l,int r,int val)
{
	if(l<=tree[x].l&&tree[x].r<=r)
	{
		tree[x].val=val;
		return;
	}
	if(tree[x].val){
		tree[x<<1].val=tree[x].val;
		tree[x<<1|1].val=tree[x].val;
		tree[x].val=0;
	}
	int mid=(tree[x].l+tree[x].r)>>1;
	if(l<=mid) query(x<<1,l,r,val);
	if(mid<r) query(x<<1|1,l,r,val);
	if(tree[x<<1].val==tree[x<<1|1].val) tree[x].val=tree[x<<1].val;
}
void print(int x)
{
	if(tree[x].val)
	{
		int lenth=tree[x].r-tree[x].l+1;
		for(int i=1;i<=lenth;i++)
			putchar(tree[x].val+'a'-1);
		return;
	}
	print(x<<1);print(x<<1|1);
}
int main()
{
	scanf("%d%d",&n,&m);
	scanf("%s",s+1);
	build(1,1,n);
	while(m--)
	{
		int l,r,op;
		scanf("%d%d%d",&l,&r,&op);
		memset(len,0,sizeof(len));
		update(1,l,r);
		if(op==1){
			for(int i=1;i<=26;i++)
				if(len[i]){
					query(1,l,l+len[i]-1,i);
					l+=len[i];
				} 
		}
		if(op==0){
			for(int i=26;i>=1;i--)
				if(len[i]){
					query(1,l,l+len[i]-1,i);
					l+=len[i];
				} 
		}
	}
	print(1);
	return 0;
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值