【树形结构】测试题D - A Simple Task

题意

一个长度为n的字符串,有q条查询。

两种操作:

1. i,j,1 把字符串从i到j的部分升序排列

2. i,j,0把字符串从i到j的部分降序排列

求q次查询之后字符串的结果

思路

训练赛的时候这题没想出来怎么写,下来查了查题解。然后分析一波,终于理解了。

就是建立26棵线段树,对应每个字母,负责记录每个字母出现的位置。

每个T内ans记录的就是该字母出现的位置,而cnt统计我们要操作的那部分的那个字母出现了几次,

然后因为要对那个区间更新,所以对这个区间可以先用0覆盖,然后再根据cnt来重新更新(其实是计数排序)

几个需要注意的地方:

1.因为有用0覆盖的操作,lazy标记应该达成-1

2.update函数应该用赋值,而不是直接套用区间更新的模板在原节点的基础上加减

代码

#include<iostream>
#include<cmath>
#include<stack>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h> 
#define Endl "\n"
typedef long long ll;
const int maxn=1e5+5;
const int mod=1e9+7;
using namespace std;


char s[maxn];
inline ll read()
{
	ll x = 0, f = 1; char ch; ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
struct sgt{
	int ans[maxn<<2],lazy[maxn<<2];
	
	void PushUp(int rt)
	{
    	ans[rt]=ans[rt<<1]+ans[rt<<1|1];
    	return ;
	}
	
	void PushDown(int rt,int ln,int rn)//ln表示左子树元素结点个数,rn表示右子树结点个数
	{
    	if (lazy[rt]!=-1)
    	{
    	    lazy[rt<<1]=lazy[rt];
    	    lazy[rt<<1|1]=lazy[rt];
    	    ans[rt<<1]=lazy[rt]*ln;
    	    ans[rt<<1|1]=lazy[rt]*rn;
    	    lazy[rt]=-1;
    	}
	}

	void Update(int L,int R,int C,int l,int r,int rt)
	{
    	if (L<=l&&r<=R)
    	{
        	ans[rt]=C*(r-l+1);
        	lazy[rt]=C;
        	return;
    	}
    	int mid=(l+r)>>1;
    	int left=rt<<1;
		int right=left|1;
    	PushDown(rt,mid-l+1,r-mid);
    	if (L<=mid) Update(L,R,C,l,mid,left);
    	if (R>mid) Update(L,R,C,mid+1,r,right);
    	PushUp(rt);
}

//查询 
	ll Query(int L,int R,int l,int r,int rt)
	{
    	if (L<=l&&r<=R)
    	    return ans[rt];
    	int mid=(l+r)>>1;
    	int left=rt<<1;
		int right=left|1;
    	PushDown(rt,mid-l+1,r-mid);//若更新只有点更新,不需要这句
    	ll ANS=0;
    	if (L<=mid) ANS+=Query(L,R,l,mid,left);
    	if (R>mid) ANS+=Query(L,R,mid+1,r,right);
    	PushUp(rt);
    	return ANS;
	} 

	
};
struct sgt T[26];

int cnt[26];

int n,q;
int main()
{
	n=read(),q=read();
	scanf("%s",s+1);
	for(int i=1;i<=n;i++)
	{
		T[s[i]-'a'].Update(i,i,1,1,n,1);
	}
	while(q--)
	{
		int a,b,key;
		a=read(),b=read(),key=read();
		if(key)
		{
			for(int i=0;i<26;i++)
				cnt[i]=T[i].Query(a,b,1,n,1);
	//			  cout<<"------test1----"<<endl;
      //     for(int i=0;i<26;i++)
       //     	cout<<cnt[i]<<" ";
        //    cout<<endl;
			for(int i=0;i<26;i++)
				T[i].Update(a,b,0,1,n,1);
			int x=a;
			for(int i=0;i<26;i++)
				if(cnt[i]!=0)
				{
					T[i].Update(x,x+cnt[i]-1,1,1,n,1);
					x+=cnt[i];
				}
		}
		else
		{
			for(int i=0;i<26;i++)
				cnt[i]=T[i].Query(a,b,1,n,1);
	//			      cout<<"------test2----"<<endl;
     //      for(int i=0;i<26;i++)
       //     	cout<<cnt[i]<<" ";
      //      cout<<endl;
			for(int i=0;i<26;i++)
				T[i].Update(a,b,0,1,n,1);
			int x=a;
			for(int i=25;i>=0;i--)
				if(cnt[i]!=0)
				{
					T[i].Update(x,x+cnt[i]-1,1,1,n,1);
					x+=cnt[i];
				}
		}
	//	cout<<q<<Endl;
	}
//	cout<<"here1"<<Endl;
	for(int i=1;i<=n;i++)
		for(int j=0;j<26;j++)
			if(T[j].Query(i,i,1,n,1))
				printf("%c",j+'a');
//	cout<<"here2"<<Endl;

	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue树形结构中勾选叶子节点可以通过以下步骤实现: 1. 首先,确保你已经引入了Vue树形组件,比如中的`VueTree`组件。 2. 确定你的树形结构的数据源,并将其绑定到Vue实例的数据中。 3. 在树形组件中,使用`v-for`指令遍历数据源,并为每个节点添加一个勾选框。 4. 给勾选框绑定一个`v-model`指令,将节点的勾选状态与Vue实例的数据进行双向绑定。 5. 当用户勾选或取消勾选一个叶子节点时,更新Vue实例中对应节点的勾选状态。 6. 根据业务需求,你可以在勾选节点时触发相应的事件或进行其他操作。 以下是一个简单的示例代码,演示了如何在Vue树形结构中勾选叶子节点: ```html <template> <div> <vue-tree :data="treeData" @node-click="handleNodeClick"></vue-tree> </div> </template> <script> import VueTree from 'vue-simple-tree/src/components/VueTree.vue'; export default { components: { VueTree }, data() { return { treeData: [ { label: 'Node 1', children: [ { label: 'Leaf 1-1', checked: false }, { label: 'Leaf 1-2', checked: false } ] }, { label: 'Node 2', children: [ { label: 'Leaf 2-1', checked: false }, { label: 'Leaf 2-2', checked: false } ] } ] }; }, methods: { handleNodeClick(node) { if (node.children) { // 如果是非叶子节点,展开或收起节点 node.expanded = !node.expanded; } else { // 如果是叶子节点,切换勾选状态 node.checked = !node.checked; } } } }; </script> ``` 在上面的代码中,`treeData`是树形结构的数据源,其中每个节点都具有`label`和`checked`属性。当用户点击一个节点时,会调用`handleNodeClick`方法来处理节点的展开和勾选操作。在`handleNodeClick`方法中,我们通过判断节点是否有子节点来确定该节点是叶子节点还是非叶子节点,并进行相应的操作。 请根据你的具体需求调整以上代码,并根据你项目中使用的树形组件的具体用法进行相应的修改。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [vue中下拉树树形结构的虚拟列表优化和ant-design-vue的form表单问题](https://blog.csdn.net/lalaladamowang/article/details/129261788)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [一个vue树形插件vue-simple-tree](https://blog.csdn.net/weixin_39845206/article/details/111893301)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值