UESTC Training for Data Structures——I

Problem  I

Problem Description

  最近,吴神被谷峰神抓去埋地雷去了,谷峰神答应吴神只要他在规定时间内完成以下任务就放他走:
  谷峰神给吴神N个数,然后有M次操作,1<=N<=100000,1<=M<=100000,每个数的范围,-10000<=ai<=10000
3类操作:
1.update i j k,把i到j这段内的每个数字加上k(-10000<=k<=10000)
2.query x,回答一个数i,i=max{j|aj>=x},如果不存在,输出-1
3.change i,j,把ai和aj的值交换一下

Input

先是case数T,然后每个case第一行两个数N和M,接下来一行N个数,接下来M行,每行一个操作。

Output

对于每次quety操作,输出答案

Sample Input

1
4 5
-2 1 3 5
update 1 3 3
query 6
change 1 3
query 6
query 10

Sample Output

3
1
-1

 

/*用线段树维护*/

#include<iostream>
#include<cstring>
#include<cmath>
#include<stdio.h>
#define N 100005
using namespace std;
struct data
{
    int be,en;
    int left,right,max_id;
    __int64 bj,max_num;
}tree[4*N];
int a[N],tot;
void make_tree(int st,int en)  //建树
{
    int now=++tot;
    tree[now].be=st; tree[now].en=en;
    if(st==en)
    {
        tree[now].max_num=a[st];
        tree[now].max_id=st;
        return;
    }
    else
    {
        int mid=(st+en)>>1;
        tree[now].left=tot+1;
        make_tree(st,mid);
        tree[now].right=tot+1;
        make_tree(mid+1,en);
        if(tree[tree[now].left].max_num>tree[tree[now].right].max_num)
        {
            tree[now].max_num=tree[tree[now].left].max_num;
            tree[now].max_id=tree[tree[now].left].max_id;
        }
        else
        {
            tree[now].max_num=tree[tree[now].right].max_num;
            tree[now].max_id=tree[tree[now].right].max_id;
        }
    }
}
void clear(int v)
{
    tree[tree[v].left].bj+=tree[v].bj;//给左儿子遗传标记
    tree[tree[v].right].bj+=tree[v].bj;//给右儿子遗传标记
    tree[v].max_num+=tree[v].bj;
    tree[v].bj=0;
}
void add(int v,int st,int en,__int64 k)  //将原数组中 第 st-->en 的所有元素的值统统加上 k
{
    if(tree[v].be>=st && tree[v].en<=en)
    {
        tree[v].bj+=k;
        return;
    }
    if(tree[v].bj!=0) clear(v);
    int mid=(tree[v].be+tree[v].en)>>1;
    if(st>mid) add(tree[v].right,st,en,k);
    else if(en<=mid) add(tree[v].left,st,en,k);
    else
    {
        add(tree[v].right,st,en,k);
        add(tree[v].left,st,en,k);
    }
    if(tree[tree[v].left].bj!=0) clear(tree[v].left);
    if(tree[tree[v].right].bj!=0) clear(tree[v].right);
    if(tree[tree[v].left].max_num>tree[tree[v].right].max_num)
    {
        tree[v].max_num=tree[tree[v].left].max_num;
        tree[v].max_id=tree[tree[v].left].max_id;
    }
    else
    {
        tree[v].max_num=tree[tree[v].right].max_num;
        tree[v].max_id=tree[tree[v].right].max_id;
    }
}
void change(int v,int k,__int64 num)//改变原数组中第k个元素的值为 num
{
    if(tree[v].be==tree[v].en && tree[v].be==k)
    {
        tree[v].max_num=num;
        return;
    }
    if(tree[v].bj) clear(v);
    if(tree[v].be==tree[v].en) return;
    int mid=(tree[v].be+tree[v].en)>>1;
    if(k<=mid) change(tree[v].left,k,num);
    if(k>mid) change(tree[v].right,k,num);
    if(tree[tree[v].left].bj) clear(tree[v].left);
    if(tree[tree[v].right].bj) clear(tree[v].right);
    if(tree[tree[v].left].max_num>tree[tree[v].right].max_num)
    {
        tree[v].max_num=tree[tree[v].left].max_num;
        tree[v].max_id=tree[tree[v].left].max_id;
    }
    else
    {
        tree[v].max_num=tree[tree[v].right].max_num;
        tree[v].max_id=tree[tree[v].right].max_id;
    }
}
__int64 get(int v,int k)  //获得原数组中第k个位置的值
{
    if(tree[v].bj!=0) clear(v);
    if(tree[v].be==tree[v].en && tree[v].be==k) return tree[v].max_num;
    int mid=(tree[v].be+tree[v].en)>>1;
    if(k>mid) return get(tree[v].right,k);
    if(k<=mid) return get(tree[v].left,k);
}
int get_id(int v,__int64 num)  //获得不小于 num 的 最大的位置的值
{
    if(tree[v].bj) clear(v);
    if(tree[v].be==tree[v].en)
    {
        if(tree[v].max_num>=num) return tree[v].max_id;
        else return -1;
    }
    if(tree[tree[v].left].bj) clear(tree[v].left);
    if(tree[tree[v].right].bj) clear(tree[v].right);
    if(tree[tree[v].right].max_num>=num) return get_id(tree[v].right,num);
    else if(tree[tree[v].left].max_num>=num) return get_id(tree[v].left,num);
    else return -1;
}
int main()
{
    int t,n,m;
    scanf("%d",&t);
    while(t--)
    {
        memset(a,0,sizeof(a));
        memset(tree,0,sizeof(tree));
        scanf("%d%d",&n,&m);
        tot=0;
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        make_tree(1,n);
        char s[10]; getchar();
        for(int i=1;i<=m;i++)
        {
            char ch; __int64 c; int k,m;
            scanf("%s%d",s,&k);
            if(s[0]=='u')
            {
                scanf("%d%I64d",&m,&c);
                add(1,k,m,c);
            }
            else if(s[0]=='c')
            {
                scanf("%d",&m);
                __int64 num1=get(1,k),num2=get(1,m);
                change(1,m,num1);
                change(1,k,num2);
            }
            else
            {
                printf("%d\n",get_id(1,k));
            }
            getchar();
        }
    }
    return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值