您的位置:首页 > 其它

hrbust 哈理工oj 1752Page Rank【线段树好题】

2016-02-12 15:08 399 查看
Page Rank
Time Limit: 1000 MSMemory Limit: 65536 K
Total Submit: 85(30 users)Total Accepted: 40(23 users)Rating: 





Special Judge: No
Description
There are n webpages, each of which has its respective page rank. The content is constantly updated and page rank is also constantly changing. Can you immediately find the page with highest weight?
Note: We set the page numbers from 1 to n.
Input
There are multiple test cases, process to the end of file.
For each test case:
Line 1: This line contains an integer n, indicating the number of pages.
Line 2: This line contains n integer, pr1, pr2, pr3, ..., prn, representing the page rank of each page.
Line 3: This line contains an integer q, indicating the number of operations.
Line 4..q+3: Each line indicating an operation.
There are two operation formats:
C i pr : change ith page's page rank to pr.
Q : query a page with the highest page rank, output the page's number and its page rank.
Limits
1<=n<=100,000
1<=q<=200,000
0<=pr<=1,000,000,000
Output
For each case:
Each "Q" query outputs a line containing the page number and page rank of the page of the highest page rank. If there is more than one page which has the highest page rank, output the page with largest number.
After each test case, output a blank line.
Sample Input
5
30 9 0 20 5
6
C 1 19
C 3 22
C 3 4
Q
C 4 12
Q
5
13 10 20 7 7
7
C 4 22
C 4 21
C 4 11
C 3 10
C 5 15
C 2 17
Q

Sample Output
4 20
1 19

2 17

这题的数据还是很屌的,我的思路实力TLE、原因是单点查询找的位子,不如大牛代码里边的区间找值定位子的方法好、所以这里直接说大牛的代码是如何实现的吧:

首先是build:

void pushup(int rt)
{
if (tree[rt<<1] > tree[rt<<1|1])//位子跟着值的变化而变化,这里也可以写成结构体,看起来方便一点。
{
tree[rt] = tree[rt<<1];
posn[rt] = posn[rt<<1];
}
else
{
tree[rt] = tree[rt<<1|1];
posn[rt] = posn[rt<<1|1];
}
}
void build(int l, int r, int rt)//大同小异的部分,
{
if (l == r)
{
scanf("%d", &tree[rt]);
posn[rt] = l;
}
else
{
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
}然后是update、
void update(int p, int val, int l, int r, int rt)
{
if (l == r)
{
tree[rt] = val;
}
else
{
int m = (l + r) >> 1;
if (p <= m)
{
update(p, val, lson);
}
else
{
update(p, val, rson);
}
pushup(rt);
}
}关键部分是query操作:
int query(int L, int R, int l, int r, int rt, int *pos)
{
if (L <= l && r <= R)//区间
{
*pos = posn[rt];
return tree[rt];
}
else
{
int m = (l + r) >> 1;
int ret1 = INT_MIN;
int ret2 = INT_MIN;
int pa, pb;
int *pos1 = &pa;
int *pos2 = &pb;
if (L <= m)
{
ret1 = query(L, R, lson, pos1);//ret1表示这部分区间的最大值,同时在这部分的query过程中,找到了pos1,表示这部分区间最大值的位子
}
if (R > m)
{
ret2 = query(L, R, rson, pos2);//ret2表示这部分区间的最大值,
}
if (ret1 > ret2)//如果ret1>ret2,无疑让pos变成pa
{
*pos = pa;
}
else//这里是关键,题目中说,如果有值相同的情况下,要输出大的位子、我们知道,rson的number总是比lson的number大,所以这里保证了题目的要求。
{
*pos = pb;
ret1 = ret2;
}
return ret1;//return最大值、
}
}

最后上完整的AC代码:

#include<cstdio>
#include<climits>
#include<algorithm>

using namespace std;

#define lson l, m, rt<<1
#define rson m+1, r, (rt<<1)|1

int tree[111111<<2];
int posn[111111<<2];
void pushup(int rt)
{
if (tree[rt<<1] > tree[rt<<1|1])
{
tree[rt] = tree[rt<<1];
posn[rt] = posn[rt<<1];
}
else
{
tree[rt] = tree[rt<<1|1];
posn[rt] = posn[rt<<1|1];
}
}
void build(int l, int r, int rt)
{
if (l == r)
{
scanf("%d", &tree[rt]);
posn[rt] = l;
}
else
{
int m = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
}
void update(int p, int val, int l, int r, int rt)
{
if (l == r)
{
tree[rt] = val;
}
else
{
int m = (l + r) >> 1;
if (p <= m)
{
update(p, val, lson);
}
else
{
update(p, val, rson);
}
pushup(rt);
}
}
int query(int L, int R, int l, int r, int rt, int *pos)
{
if (L <= l && r <= R)
{
*pos = posn[rt];
return tree[rt];
}
else
{
int m = (l + r) >> 1;
int ret1 = INT_MIN;
int ret2 = INT_MIN;
int pa, pb;
int *pos1 = &pa;
int *pos2 = &pb;
if (L <= m)
{
ret1 = query(L, R,  lson, pos1);
}
if (R > m)
{
ret2 = query(L, R, rson, pos2);
}
if (ret1 > ret2)
{
*pos = pa;
}
else//这里保证最大位子优先、
{
*pos = pb;
ret1 = ret2;
}
return ret1;
}
}
int main(void)
{
int n, m;

while (scanf("%d", &n) != EOF)
{
build(1, n, 1);

scanf("%d", &m);
char op[2];
int a, b;
while (m--)
{
scanf("%s", op);
if (op[0] == 'Q')
{
int pos;
printf("%d %d\n", pos, query(1, n, 1, n, 1, &pos));
}
else
{
scanf("%d%d", &a, &b);
update(a, b, 1, n, 1);
}
}
printf("\n");
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息