列表

详情


NC208615. 区间第k大

描述

有一列长为的数列A,有m个询问和修改:

对于询问,表示A中询问区间[l,r]中第k大的数是多少。(如果某数在区间中最大值的个数超过两个时次大值等于最大值)

对于修改,表示修改A中第pos个数为x

输入描述

一个数n,表示数列A长度为n。

接下来一行n个数表示数列A。

下一行接一个数m表示有m个询问。

对于询问:格式为,1表示询问,l、r表示询问的区间,k表示第k大。

对于修改:格式为,2表示修改,pos表示修改的位置,x表示修改为x。

输出描述

对于每个询问输出一个数表示答案。

示例1

输入:

5
1 2 3 4 5
4
1 1 3 2
2 1 3
1 1 3 1
1 4 5 2

输出:

2
3
4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 791ms, 内存消耗: 5208K, 提交时间: 2020-07-06 11:35:56

#include<bits/stdc++.h>
using namespace std;
class tree{
public:
    int l,r,maxn,p;//p存最大点坐标
};
class tree tt[400100];
int p[100100];
void buildtree(int node,int l,int r){
    if(l==r){
        tt[node].l=l,tt[node].r=r;
        tt[node].maxn=p[l];
        tt[node].p=l;
        return;
    }
    else{
    int mid=(l+r)>>1;
    buildtree(node<<1,l,mid);
    buildtree((node<<1)+1,mid+1,r);
    tt[node].l=l,tt[node].r=r;
    tt[node].maxn=max(tt[node<<1].maxn,tt[(node<<1)+1].maxn);
    if(tt[node].maxn==tt[node<<1].maxn)tt[node].p=tt[node<<1].p;
    else tt[node].p=tt[(node<<1)+1].p;
    }
}
void updatatree(int pos,int node,int x){
    if(tt[node].l==tt[node].r){
        tt[node].maxn=x;
        return;
    }
    int mid=(tt[node].l+tt[node].r)>>1;
    if(pos<=mid)updatatree(pos,node<<1,x);
    if(pos>mid)updatatree(pos,(node<<1)+1,x);
    tt[node].maxn=max(tt[node<<1].maxn,tt[(node<<1)+1].maxn);
	if(tt[node].maxn==tt[node<<1].maxn)tt[node].p=tt[node<<1].p;
    else tt[node].p=tt[(node<<1)+1].p;
}
 class tree findmax(int node,int l,int r){
    if(tt[node].l>=l&&tt[node].r<=r)
        return tt[node];
    int mid=(tt[node].l+tt[node].r)>>1;
    class tree max1;
    max1.maxn=-1;
    if(l<=mid)max1=findmax(node<<1,l,r);
    if(r>mid)if(max1.maxn<findmax((node<<1)+1,l,r).maxn){
        max1=findmax((node<<1)+1,l,r);
    }
    return max1;
}
int main(){
    int n,ww,pos,l,r,k,y,x;
    class tree f;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&p[i]);
    buildtree(1,1,n);
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&ww);
        if(ww==1){
            scanf("%d%d%d",&l,&r,&k);
            if(k==1){
                f=findmax(1,l,r);
                printf("%d\n",f.maxn);
            }
            else{
                f=findmax(1,l,r);
                x=f.maxn,y=f.p;
                updatatree(f.p,1,-1);
                f=findmax(1,l,r);
				printf("%d\n",f.maxn);
                updatatree(y,1,x);
            }
        }
        else{
            scanf("%d%d",&pos,&k);
            updatatree(pos,1,k);
        }
    }
}

C++11(clang++ 3.9) 解法, 执行用时: 192ms, 内存消耗: 4832K, 提交时间: 2020-07-05 14:43:27

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5+10;
struct node{
	int val,p;
	bool operator < (const node& t)const {
		return val < t.val;
	}
	
};

node tr[maxn * 4];
#define ls o<<1
#define rs o<<1|1
#define mid (l+r)/2
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r

void up(int o,int l,int r,int p,int val)
{
	if(l == r)
	{
		tr[o].val = val;
		tr[o].p = l;
		return ;
	}
	if(p <= mid)up(lson,p,val);
	else up(rson,p,val);
	if(tr[ls] < tr[rs])tr[o] = tr[rs];
	else tr[o] = tr[ls];
}
node qu(int o,int l,int r,int L,int R)
{
	if(l >= L && r <= R)return tr[o];
	node ans = node{-1000000000,0};
	if(L <= mid)
	{
		node tmp = qu(lson,L,R);
		if(ans < tmp)ans = tmp;
	}
	if(R > mid)
	{
		node tmp = qu(rson,L,R);
		if(ans < tmp)ans = tmp;
	}
	return ans;
}
int main()
{
	int n,x;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		up(1,1,n,i,x);
	}
	int q;
	scanf("%d",&q);
	while(q--)
	{
		int op,l,r,k;
		scanf("%d",&op);
		if(op == 1)
		{
			scanf("%d%d%d",&l,&r,&k);
			node ans = qu(1,1,n,l,r);
			if(k == 1)printf("%d\n",ans.val);
			else {
				up(1,1,n,ans.p,-1);
				printf("%d\n",qu(1,1,n,l,r).val);
				up(1,1,n,ans.p,ans.val);
			}
		}
		else 
		{
			scanf("%d%d",&l,&r);
			up(1,1,n,l,r);
		}
	}
 } 

上一题