JDOJ 2943: 线段树、树套树、分块
Description
给出一个序列,要求支持以下操作:
1 x y : 输出[x,y]中最大的数字。
2 x y : 将序列的第x个数字改成y。
Input
第一行一个整数n,表示数列的长度。
第二行n个数,表示初始的序列。
第三行一个整数m,表示操作数量。
接下来m行,每行可能是1 x y,或者2 x y,意义如上。
强制在线,记上一次输出的答案为last_ans(last_ans初值为0):
对于第一个操作1 x y
x = min((x + last_ans) % n + 1, (y + last_ans) % n + 1)
y = max((x + last_ans) % n + 1, (y + last_ans) % n + 1)
对于第二个操作2 x y
x = (x + last_ans) % n + 1
y = (y + last_ans) % n + 1
Output
对于每个1操作,输出[x,y]中的最大值。
Sample Input
10 10 4 6 2 3 1 8 3 5 7 5 1 4 5 2 5 9 2 9 5 1 2 10 1 1 1
Sample Output
3 3 3
HINT
n, m <= 100000
BY JYZ
题解:
模板。
线段树。
注意强制在线的处理。
代码:
#include<cstdio>
#include<algorithm>
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
const int maxn=1e5+10;
int n,m,last;
int a[maxn];
int tree[maxn<<2];
void build(int pos,int l,int r)
{
int mid=(l+r)>>1;
if(l==r)
{
tree[pos]=a[l];
return;
}
build(lson,l,mid);
build(rson,mid+1,r);
tree[pos]=max(tree[lson],tree[rson]);
}
void update(int pos,int l,int r,int x,int k)
{
int mid=(l+r)>>1;
if(l==r)
{
tree[pos]=k;
return;
}
if(x<=mid)
update(lson,l,mid,x,k);
else
update(rson,mid+1,r,x,k);
tree[pos]=max(tree[lson],tree[rson]);
}
int query(int pos,int l,int r,int x,int y)
{
int ret=-1;
int mid=(l+r)>>1;
if(x<=l && r<=y)
return tree[pos];
if(x<=mid)
ret=max(ret,query(lson,l,mid,x,y));
if(y>mid)
ret=max(ret,query(rson,mid+1,r,x,y));
return ret;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
scanf("%d",&m);
while(m--)
{
int opt,x1,y1,x,y;
scanf("%d%d%d",&opt,&x1,&y1);
if(opt==1)
{
x=min((x1+last)%n+1,(y1+last)%n+1);
y=max((x1+last)%n+1,(y1+last)%n+1);
last=query(1,1,n,x,y);
printf("%d
",last);
}
else
{
x=(x1+last)%n+1;
y=(y1+last)%n+1;
update(1,1,n,x,y);
}
}
return 0;
}