题目描述:
有一条河,沿河的一侧生活着一个部落。这个一字型的部落有n个据点,从左至右依次编号1~n。
部落的人们有时会在某个据点建立建筑,每个建筑都有各自的价值。一开始,每个据点的都没有建筑,价值都是0。如果在已有建筑的据点建立新的建筑,那么新的建筑会代替旧的建筑(旧的建筑就此消失)。
有两种操作C和Q:
1、C x y,表示在据点x建立一个价值为y的建筑。
2、Q x y,询问在据点x~y之间(包括x,y)的建筑中,价值第八大的建筑的价值是多少。
输入描述:
第一行,两个正整数n和k,表示据点的数量和操作的数量。
接下的k行,每行一个操作。
输出描述:
对于所有的Q操作,输出相应的第八大建筑的价值。
输入样例:
10 14
C 1 5
C 2 4
C 3 7
C 4 6
C 5 5
C 6 1
C 7 8
Q 1 10
C 8 3
C 9 6
C 10 3
Q 1 9
C 6 10
Q 1 10
输出样例:
0
3
4
思路:唉,当时要是能想到这一点,也不会只拿个国二了。
很明显,区间操作,线段树是很容易想到的。但是这次线段树的每一个节点不是维护一个数了,而是8个数。因为8很小,所以还是可以承担的。每次pushup的时候,将最大的八个数更新给父节点。查询的时候返回一个数组就可以了。代码没有测试,不知道有没有问题,当个参考吧。
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=1e5+100;
struct node{
int l;
int r;
int a[9];
int len;
}p[maxx<<2];
int n,m,x,y;
inline void pushup(int cur)
{
int *c1=new int[9];
int *c2=new int[9];
int len1=p[cur<<1].len;
int len2=p[cur<<1|1].len;
sort(p[cur<<1].a,p[cur<<1].a+len1);
sort(p[cur<<1|1].a,p[cur<<1|1].a+len2);
c1=p[cur<<1].a;
c2=p[cur<<1|1].a;
int len=0;len1--,len2--;
while(len<8&&(len1>=0&&len2>=0))
{
if(c1[len1]>c2[len2]) p[cur].a[len++]=c1[len1],len1--;
else p[cur].a[len++]=c2[len2],len2--;
}
if(len1==-1) while(len<8&&len2>=0) p[cur].a[len++]=c2[len2--];
else while(len<8&&len1>=0) p[cur].a[len++]=c1[len1--];
while(len<8) p[cur].a[len++]=0;
p[cur].len=len;
}
inline void build(int l,int r,int cur)
{
p[cur].l=l;
p[cur].r=r;
p[cur].len=0;
memset(p[cur].a,0,sizeof(p[cur].a));
if(l==r) return ;
int mid=l+r>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
}
inline void update(int pos,int v,int cur)
{
int L=p[cur].l;
int R=p[cur].r;
if(L==R)
{
p[cur].a[0]=v;
p[cur].len=1;
return ;
}
int mid=L+R>>1;
if(pos<=mid) update(pos,v,cur<<1);
else update(pos,v,cur<<1|1);
pushup(cur);
}
inline int *query(int l,int r,int cur)
{
int L=p[cur].l;
int R=p[cur].r;
if(l<=L&&R<=r) return p[cur].a;
int mid=L+R>>1;
if(r<=mid) return query(l,r,cur<<1);
else if(l>mid) return query(l,r,cur<<1|1);
else
{
int *c1=new int[9];
c1=query(l,mid,cur<<1);
int *c2=new int[9];
c2=query(mid+1,r,cur<<1|1);
sort(c1,c1+8);
sort(c2,c2+8);
int *c=new int[9];
int len=0,len1=7,len2=7;
while(len<8&&(len1>=0&&len2>=0))
{
if(c1[len1]>c2[len2]) c[len++]=c1[len1],len1--;
else c[len++]=c2[len2],len2--;
}
if(len1==-1) while(len<8&&len2>=0) c[len++]=c2[len2--];
else while(len<8&&len1>=0) c[len++]=c1[len1--];
return c;
}
}
int main()
{
scanf("%d%d",&n,&m);
build(1,n,1);
char s[2];
while(m--)
{
scanf("%s%d%d",s,&x,&y);
if(s[0]=='C') update(x,y,1);
else
{
int *c=new int[9];
c=query(x,y,1);
sort(c,c+8);
printf("%d\n",c[0]);
}
}
return 0;
}
努力加油a啊,(o)/~