RMQ With Shift

  • 题目
  • 题意:query就是查询,shift( a, b, c)则是单点修改,将区间的a, b, c位置的值交换,即 a位置换成 b位置的值,b位置换成  c位置的值,c位置换成 a位置的值。
  • 题解:只要理解了题意就是一道简单的单点修改,区间查询的线段树问题。
  • 注意:字符串转化为数字的时候记得考虑是几位数,每次都当作个位数处理了(捂脸

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define LL long long
    const int maxn = 1e5 + 5, INF = 0x3f3f3f; 
    using namespace std;
    struct node{
    	int mi;
    }tree[maxn * 4 + 10];
    int pos[maxn], cnt = 0;
    void pushup(int p,int l,int r)
    {
    	if(l < r){
    		tree[p].mi = min(tree[p << 1].mi, tree[p << 1 | 1].mi);
    	}
    }
    void build(int l,int r,int p)
    {
    	if(l == r){
    		scanf("%d",&tree[p].mi);
    		pos[++cnt] = p;
    		return ;
    	} 
    	int mid = (l + r) >> 1;
    	build(l,mid,p << 1);
    	build(mid+1,r,p << 1 | 1);
    	pushup(p,l,r);
    	return; 
    }
    void update(int nl,int nr,int px,int d,int p)
    {
    	if(nl == nr)
    	{
    		tree[p].mi = d;
    		return ;
    	}
    	int mid = (nl + nr) >> 1;
    	if(px <= mid) update(nl, mid, px, d, p << 1);
    	if(mid < px) update(mid+1, nr, px, d, p << 1 | 1);
    	pushup(p,nl,nr);
    	return; 
    }
    LL query(int l, int r, int nl, int nr, int p)
    {
    	if(nl >= l && nr <= r){
    		return tree[p].mi;
    	}
    	LL res = INF;
    	int mid = (nl + nr) >> 1;
    	if(l <= mid) res = min(res, query(l, r, nl, mid, p << 1));
    	if(mid < r) res = min(res, query(l, r, mid+1, nr, p << 1 | 1));
    	return res; 
    }
    int main()
    {
    	int n,q,num[maxn] = {0};
    	char str[maxn] = {0};
    	scanf("%d%d",&n,&q);
    	build(1,n,1);
    	while(q--)
    	{
    		scanf(" %s",str);
    		if(str[0] == 'q')
    		{
    			int i = 6, j = 0;
    			while(str[i])
    			{
    				while(str[i] >= '0' && str[i] <= '9')
    				{
    					num[j] = num[j] * 10 + (str[i] - '0'); //记得乘10
    					++i;
    				}
    				++j;++i;
    			}
    			printf("%lld\n",query(num[0],num[1],1,n,1));
    			num[0] = 0, num[1] = 0;
    		}
    		else
    		{
    			int i = 6, j = 1;
    			while(str[i])
    			{
    				while(str[i] >= '0' && str[i] <= '9'){
    					num[j] = num[j] * 10 + (str[i] - '0');
    					++ i;
    				}
    				++ i; ++ j;
    			}
    			int mark = tree[pos[num[1]]].mi;
    			for(int i = 1; i < j; ++ i)
    			{
    				update(1,n,num[i],tree[pos[num[i+1]]].mi,1);
    			}
    			update(1,n,num[j-1],mark,1);
    			memset(num,0,sizeof(num));
    		}
    	}
    	return 0;
    }

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值