HDU1754-I Hate It

I Hate It

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


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 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
 

Author
linle
 

Source
 

Recommend
lcy
 
解题思路:线段树(Splay练手题)

线段树:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <set>
#include <stack>
#include <map>
#include <climits>

using namespace std;

#define LL long long
const int INF=0x3f3f3f3f;

struct node
{
    int l,r,num;
}a[800000];
int b[200009];

void build(int l,int r,int k)
{
    a[k].l=l;
    a[k].r=r;
    if(r==l) a[k].num=b[l];
    else
    {
        build(l,(l+r)/2,k*2);
        build((l+r)/2+1,r,k*2+1);
        a[k].num=max(a[2*k].num,a[2*k+1].num);
    }
}

int query(int l,int r,int k)
{
    int ans=-1;
    if(l<=a[k].l&&r>=a[k].r) return a[k].num;
    else
    {
        int mid=(a[k].l+a[k].r)/2;
        if(mid>=l) ans=max(ans,query(l,r,k<<1));
        if(mid<r) ans=max(ans,query(l,r,k<<1|1));
    }
    return ans;
}

void f(int s,int val,int k)
{
    if(a[k].l==s&&a[k].r==s)
    {
        a[k].num=val;
        return ;
    }
    int mid=(a[k].l+a[k].r)>>1;
    if(s<=mid) f(s,val,k<<1);
    else f(s,val,k<<1|1);
    a[k].num=max(a[k<<1].num,a[k<<1|1].num);
}

int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=1; i<=n; i++)
            scanf("%d",&b[i]);
        build(1,n,1);
        string s;
        int l,r;
        while(m--)
        {
            cin>>s;
            if(s=="Q")
            {
                scanf("%d %d",&l,&r);
                printf("%d\n",query(l,r,1));
            }
            else
            {
                scanf("%d %d",&l,&r);
                f(l,r,1);
            }
        }
    }
    return 0;
}


Splay:

#include <iostream>     
#include <cstdio>     
#include <cstring>     
#include <string>     
#include <algorithm>     
#include <map>     
#include <set>     
#include <stack>     
#include <queue>     
#include <vector>     
#include <bitset>     
#include <functional>  

using namespace std;

#define LL long long  

const int maxn = 2e5 + 10;
int n, m, l, r, root, a[maxn];
char ch[10];

struct Splays
{
	const static int maxn = 2e5 + 10;
	const static int INF = 0x7FFFFFFF;
	int son[maxn][2], fa[maxn], tot;
	int val[maxn], ma[maxn], id[maxn];

	int Node(int f, int v)
	{
		son[tot][0] = son[tot][1] = 0;
		fa[tot] = f, val[tot] = ma[tot] = v;
		return tot++;
	}

	void clear()
	{
		son[0][0] = son[0][1] = fa[0] = 0;
		ma[0] = -INF, tot = 1;
	}

	void rotate(int k, int p)
	{
		int y = fa[k];
		son[y][!p] = son[k][p], fa[son[k][p]] = y;
		if (fa[y]) son[fa[y]][y == son[fa[y]][1]] = k;
		fa[k] = fa[y], fa[y] = k, son[k][p] = y;
		ma[k] = ma[y], ma[y] = max(val[y], max(ma[son[y][0]], ma[son[y][1]]));
	}

	void Splay(int k, int p)
	{
		for (int f = fa[p]; fa[k] != f;)
		{
			if (fa[fa[k]] == f) { rotate(k, k == son[fa[k]][0]); return; }
			int y = (k == son[fa[k]][0]), z = (fa[k] == son[fa[fa[k]]][0]);
			y^z ? (rotate(k, y), rotate(k, z)) : (rotate(fa[k], z), rotate(k, y));
		}
	}

	void build(int &k, int l, int r, int f)
	{
		if (l > r) return;
		int mid = l + r >> 1;
		id[mid] = k = Node(f, a[mid]);
		build(son[k][0], l, mid - 1, k);
		build(son[k][1], mid + 1, r, k);
		ma[k] = max(val[k], max(ma[son[k][0]], ma[son[k][1]]));
	}

	void change(int &k, int p, int v)
	{
		Splay(id[p], k); k = id[p];
		val[k] = v;
		ma[k] = max(v, max(ma[son[k][0]], ma[son[k][1]]));
	}

	void find(int &k, int l, int r)
	{
		Splay(id[l - 1], k), k = id[l - 1];
		Splay(id[r + 1], son[k][1]), son[k][1] = id[r + 1];
		printf("%d\n", ma[son[son[k][1]][0]]);
	}
}solve;

int main()
{
	while (~scanf("%d%d", &n, &m))
	{
		solve.clear();
		a[0] = a[n + 1] = -0x7FFFFFFF;
		root = 0;
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
		solve.build(root, 0, n + 1, 0);
		while (m--)
		{
			scanf("%s%d%d", ch, &l, &r);
			if (ch[0] == 'Q') solve.find(root, l, r);
			else solve.change(root, l, r);
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值