I Hate It HDU - 1754 伸展树

很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
这让很多学生很反感。

不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。

Input
本题目包含多组测试,请处理到文件结束。
在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
学生ID编号分别从1编到N。
第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。
Output
对于每一次询问操作,在一行里面输出最高成绩。
Sample Input
5 6
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 2 9
Q 1 5
Sample Output
5
6
5
9


        
  
Hint
Huge input,the C function scanf() will work better than cin 



恍恍惚惚之间AC,之前做过区间更新的,需要在每个值上面加一个数?还需要用lazy,这个题想了一下应该不需要lazy,基于区间加和,我发现直接更新这个数可能没什么问题,等到下次查询的时候同区间和一样,通过两次旋转就可以完成区间的更新,于是就这么写了一下,突然AC,猝不及防

#include <iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define MAXN 200010
struct Node
{
    int key, sz, cnt, Max;
    Node *ch[2], *pnt;
    Node() {}
    Node(int x, int y, int z)
    {
        key = x, sz = y, cnt = z,Max=0;
    }
    void rs()
    {
        sz = ch[0]->sz + ch[1]->sz + cnt;
        Max=max(max(ch[0]->Max,ch[1]->Max),key);
    }
} nil(0, 0, 0), *NIL = &nil;
struct Splay
{
    Node *root;
    int ncnt;
    Node nod[MAXN];
    void init()
    {
        root = NIL;
        ncnt = 0;
    }
    void rotate(Node *x, bool d)
    {
        Node *y = x->pnt;
        y->ch[!d] = x->ch[d];
        if (x->ch[d] != NIL)
            x->ch[d]->pnt = y;
        x->pnt = y->pnt;
        if (y->pnt != NIL)
        {
            if (y == y->pnt->ch[d])
                y->pnt->ch[d] = x;
            else
                y->pnt->ch[!d] = x;
        }
        x->ch[d] = y;
        y->pnt = x;
        y->rs();
    }
    void splay(Node *x, Node *target) //将x伸展到target的儿子位置处
    {
        Node *y;
        while (x->pnt != target)
        {
            y = x->pnt;
            if (x == y->ch[0])
            {
                if (y->pnt != target && y == y->pnt->ch[0])
                    rotate(y, true);
                rotate(x, true);
            }
            else
            {
                if (y->pnt != target && y == y->pnt->ch[1])
                    rotate(y, false);
                rotate(x, false);
            }
        }
        x->rs();
        if (target == NIL)
            root = x;
    }
    /************************以上一般不用修改************************/
    void insert(int key) //插入一个值
    {
        if (root == NIL)
        {
            ncnt = 0;
            root = &nod[++ncnt];
            root->ch[0] = root->ch[1] = root->pnt = NIL;
            root->key = key;
            root->sz = root->cnt = 1;
            root->Max=key;
            return;
        }
        Node *x = root, *y;
        while (1)
        {
            x->sz++;
            x->Max=max(x->Max,key);
            if (x->ch[1] != NIL)
                x = x->ch[1];
            else
            {
                x->ch[1] = &nod[++ncnt];
                y = x->ch[1];
                y->key = key;
                y->sz = y->cnt = 1;
                y->ch[0] = y->ch[1] = NIL;
                y->pnt = x;
                y->Max=key;
                break;
            }
        }
        splay(y, NIL);
    }
    Node* findk(int kth)
    {
        if (root == NIL || kth > root->sz)
            return NIL;
        Node *x = root;
        while (1)
        {
            if (x->ch[0]->sz +1 <= kth && kth <= x->ch[0]->sz + x->cnt)
                break;
            else if (kth <= x->ch[0]->sz)
                x = x->ch[0];
            else
            {
                kth -= x->ch[0]->sz + x->cnt;
                x = x->ch[1];
            }
        }
        splay(x, NIL);
        return x;
    }
    void update(int pos,int val)
    {
        Node * st=findk(pos+1);
        st->key=val;
        splay(st,NIL);
    }
    int query(int l,int r)
    {
        Node * s=findk(l);
        Node * t=findk(r+2);
        splay(s,NIL);
        splay(t,root);
        return root->ch[1]->ch[0]->Max;
    }
} sp;
int main()
{
    int n,q;
    while(scanf("%d%d",&n,&q)!=EOF)
    {
        sp.init();
        sp.insert(0);
        for(int i=0; i<n; i++)
        {
            int tep;
            scanf("%d",&tep);
            sp.insert(tep);
        }
        sp.insert(0);
        while(q--)
        {
            char op[10];
            scanf("%s",op);
            if(op[0]=='U')
            {
                int pos,val;
                scanf("%d%d",&pos,&val);
                sp.update(pos,val);
            }
            else
            {
                int l,r;
                scanf("%d%d",&l,&r);
                int ans=sp.query(l,r);
                printf("%d\n",ans);
            }
        }
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值