hdu1754 I Hate It(splay或者线段树)

来源:互联网 发布:电脑硬盘恢复数据 编辑:程序博客网 时间:2024/06/06 01:34

I Hate It

Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 27434    Accepted Submission(s): 10889


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

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

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 61 2 3 4 5Q 1 5U 3 6Q 3 4Q 4 5U 2 9Q 1 5
 

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

Author
linle

我的第一道splay~

题目大意:中文题,不解释。

题目分析:单点更新,区间查询,线段树入门级题目。

不过此题可以用很多数据结构做。

今天用这道题练习一下第一道splay,虽然杀鸡不需要用牛刀。

直接上代码:

#include <iostream>#include<cstdio>#include<cstring>using namespace std;const int N = 210000;const int INF = 0x3f3f3f3f;struct node{    int f,l,r,val,mx,pos,size;}tree[N];int next[N];int lcm[N];int m,n;int Max(int a,int b){    return a > b?a:b;}void init(){    tree[0].size = 0;    for(int i = 0;i < N - 1;i ++)        next[i] = i + 1;}int newnode(int pos,int key){    int p = next[0];    next[0] = next[p];    tree[p].val = key;    tree[p].pos = pos;    tree[p].f = tree[p].l = tree[p].r = 0;    tree[p].size = 1;    return p;}void delnode(int p){    next[p] = next[0];    next[0] = p;}void push_up(int rt){    if(!rt)        return;    int ll = tree[rt].l;    int rr = tree[rt].r;    tree[rt].size = 1 + (tree[ll].size + tree[rr].size);    tree[rt].mx = Max(tree[rt].val,Max(tree[ll].mx,tree[rr].mx));}void zig(int x){    int p = tree[x].f;    tree[p].l = tree[x].r;    if(tree[x].r)        tree[tree[x].r].f = p;    push_up(p);    tree[x].r = p;    push_up(x);    tree[x].f = tree[p].f;    tree[p].f = x;    if(tree[tree[x].f].pos > tree[x].pos)//left child        tree[tree[x].f].l = x;    else        tree[tree[x].f].r = x;}void zag(int x){    int p = tree[x].f;    tree[p].r = tree[x].l;    if(tree[x].l)        tree[tree[x].l].f = p;    push_up(p);    tree[x].l = p;    push_up(x);    tree[x].f = tree[p].f;    tree[p].f = x;    if(tree[tree[x].f].pos > tree[x].pos)//left child        tree[tree[x].f].l = x;    else        tree[tree[x].f].r = x;}int splay(int x,int fa)//将x节点splay到fa节点下面{    int p;    while(tree[x].f != fa)    {        p = tree[x].f;//parent node        if(tree[p].f == fa)        {            if(tree[p].l == x)//left tree                zig(x);            if(tree[p].r == x)                zag(x);        }        else        {            int g = tree[p].f;//grandparent node            if(tree[g].l == p && tree[p].l == x)//ll            {                zig(p);                zig(x);            }            else if(tree[g].l == p && tree[p].r == x)//lr            {                zag(x);                zig(x);            }            else if(tree[g].r == p && tree[p].l == x)//rl            {                zig(x);                zag(x);            }            else if(tree[g].r == p && tree[p].r == x)//rr            {                zag(p);                zag(x);            }        }    }    return x;}int build(int l,int r,int fa){    if(l > r)        return 0;    int mid = (l + r)>>1;    int p = newnode(mid,lcm[mid]);    tree[p].pos = mid;    tree[p].f = fa;    tree[p].l = build(l,mid - 1,p);    tree[p].r = build(mid + 1,r,p);    push_up(p);    return p;}void prepare(int &root){    root = newnode(0,-INF);    tree[root].r = newnode(n + 1,-INF);    tree[tree[root].r].f = root;    tree[tree[root].r].l = build(1,n,tree[root].r);}int find(int pos,int root){    if(!root)        return 0;    if(pos == tree[root].pos)        return root;    if(pos > tree[root].pos)        return find(pos,tree[root].r);    else        return find(pos,tree[root].l);}void update(int pos,int val,int &root){    int q = find(pos,root);    if(q)        root = splay(q,tree[root].f);    else        return;    tree[root].val = val;if(tree[root].val > tree[root].mx)tree[root].mx = tree[root].val;}int main(){    int root;    int i,a,b;    char op[3];    while(~scanf("%d%d",&n,&m))    {        init();        for(i = 1;i <= n;i ++)            scanf("%d",&lcm[i]);        prepare(root);        while(m --)        {            scanf("%s",op);            scanf("%d%d",&a,&b);            if(op[0] == 'U')                update(a,b,root);            else            {                int tp = find(a - 1,root);                if(tp)                    root = splay(tp,tree[root].f);                tp = find(b + 1,root);                if(tp)                    tree[root].r = splay(tp,root);//tree[root].r);                printf("%d\n",tree[tree[tree[root].r].l].mx);            }        }    }    return 0;}//671MS7340K

附上线段树代码:

#include <iostream>#include<cstdio>#include<cstring>using namespace std;const int N = 200001;int tree[N<<2];int lcm[N];int m,n;int Max(int a,int b){    return a > b?a:b;}void build(int num,int s,int e){    if(s == e)    {        tree[num] = lcm[s];        return;    }    int mid = (s + e)>>1;    build(num<<1,s,mid);    build(num<<1|1,mid + 1,e);    tree[num] = Max(tree[num<<1],tree[num<<1|1]);}void update(int num,int s,int e,int pos,int val){    if(s == e)    {        tree[num] = val;        return;    }    int mid = (s + e)>>1;    if(pos <= mid)        update(num<<1,s,mid,pos,val);    else        update(num<<1|1,mid + 1,e,pos,val);    tree[num] = Max(tree[num<<1],tree[num<<1|1]);}int query(int num,int s,int e,int l,int r){    if(s == l && r == e)        return tree[num];    int mid = (s + e)>>1;    if(r <= mid)        return query(num<<1,s,mid,l,r);    else    {        if(l > mid)            return query(num<<1|1,mid + 1,e,l,r);        else            return Max(query(num<<1,s,mid,l,mid),query(num<<1|1,mid + 1,e,mid + 1,r));    }}int main(){    int i,a,b,c;    char op[4];    while(~scanf("%d%d",&n,&m))    {        for(i = 1;i <= n;i ++)            scanf("%d",&lcm[i]);        build(1,1,n);        while(m --)        {            scanf("%s",op);            scanf("%d%d",&a,&b);            if(op[0] == 'U')                update(1,1,n,a,b);            else                printf("%d\n",query(1,1,n,a,b));        }    }    return 0;}//218MS3068K
这题线段树效率貌似高些。