列表

详情


NC222134. 未曾设想的道路

描述

的家外面有一座山,小 会将这座山分成  段,对于每一段高度相当于是相同的,常年以来,这些山的高度会因为自然因素和人为因素的影响产生改变,小 对这些山很感兴趣,希望知道历史以来一段山中出现过的第  高的山的高度。

输入描述

第一行两个整数 ,小  将家门口的山分成  段,有  个操作。
第二行有  个整数,表示最开始时山的高度。
接下来  行,每行若干整数,第一个数为操作的编号 
 到  这些段的山因为一些自然因素和人为因素的影响,高度都增加了  不一定是大于 )。
:小  想知道在  到  这些段的山中出现过的所有高度所构成的中第  大的高度。

输出描述

对于每个操作 1 输出一个答案,每个答案输出占一行,如果不存在第  大的高度则输出历史以来的最小值。

示例1

输入:

8 8
87 -90 95 38 71 -98 -90 -56
1 1 7 1
0 5 8 31
0 1 5 61
0 3 7 5
0 2 3 -46
1 3 5 3
0 1 5 -25
0 4 6 -30

输出:

95
161

说明:

开始时的序列为 (其中  表示一个可重集,即对应位置出现过的数)。
查询  的并集  中的最大值为
在接下来的  次修改后序列为 
查询  的并集  中第  大的值为

原站题解

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

C++(g++ 7.5.0) 解法, 执行用时: 5761ms, 内存消耗: 311796K, 提交时间: 2022-10-24 21:38:45

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10,K=100,inf=0x3f3f3f3f,cp=-1e7;
struct node{
    int l,r;
    int v[K],s[K],add,a[K];
}tr[N<<2];
int a[N];
int n,m;
void add(int a[], int b[], int c[]) {
    priority_queue <pair<int, int>> P;
    for (int i=0; i<K; i++) {
        P.push({a[0] + b[i], 0});
    }
    for (int i=0; i<K; i++) {
        auto u = P.top(); P.pop();
        c[i] = u.first;
        if (i == K - 1) break;
        P.push({u.first - a[u.second] + a[u.second + 1], u.second + 1});
    }
}
void merge(int a[],int b[],int c[]){
    for(int i=0,j=0,k=0;i<K;){
        if(a[j]>=b[k])c[i++]=a[j++];
        else c[i++]=b[k++];
    }
}
void merge(int a[],int b[]){
    int f[K];
    for(int i=0,j=0,k=0;i<K;){
        if(a[j]>=b[k])f[i++]=a[j++];
        else f[i++]=b[k++];
    }
    for(int i=0;i<K;++i)a[i]=f[i];
}
void pushdown(int rt){
    if (tr[rt].s[0] > cp) {
        for (auto ch : {rt<<1, rt<<1|1}) {
            int f[K];
 
            add(tr[ch].v, tr[rt].s, f);
            merge(tr[ch].a, f);
 
            for (int i=0; i<K; i++) f[i] = tr[ch].add + tr[rt].s[i];
            merge(tr[ch].s, f);
 
            tr[ch].add += tr[rt].add;
            for (int i=0; i<K; i++) tr[ch].v[i] += tr[rt].add;
        }
 
        tr[rt].add = 0;
        for (int i=0; i<K; i++) tr[rt].s[i] = -inf;
    }
}
void build(int k,int l,int r){
    tr[k]={l,r};
    for(int i=0;i<K;++i)tr[k].s[i]=-inf;
    if(l==r){
        tr[k].v[0]=a[l];
        for(int i=1;i<K;++i)tr[k].v[i]=-inf;
        for(int i=0;i<K;++i)tr[k].a[i]=tr[k].v[i];
        return ;
    }
    int mid=l+r>>1;
    build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    merge(tr[k<<1].v,tr[k<<1|1].v,tr[k].v);
    for(int i=0;i<K;++i)tr[k].a[i]=tr[k].v[i];
}
void update(int k,int l,int r,int x){
    if(tr[k].l>=l&&r>=tr[k].r){
        for(int i=0;i<K;++i)tr[k].v[i]+=x;
        merge(tr[k].a,tr[k].v);
        tr[k].add+=x;
        for(int i=0;i<K;++i){
            if(tr[k].add>tr[k].s[i]){
                for(int j=K-1;j>i;j--){
                    tr[k].s[j]=tr[k].s[j-1];
                }
                tr[k].s[i]=tr[k].add;
                break;
            }
        }
        return ;
    }
    pushdown(k);
    int mid=tr[k].l+tr[k].r>>1;
    if(mid>=l)update(k<<1,l,r,x);
    if(mid<r)update(k<<1|1,l,r,x);
    merge(tr[k<<1].v,tr[k<<1|1].v,tr[k].v);
    merge(tr[k<<1].a,tr[k<<1|1].a,tr[k].a);
}
int ans[K];
void query(int k,int l,int r){
    if(tr[k].l>=l&&tr[k].r<=r){
        merge(ans,tr[k].a);
        return;
    }
    pushdown(k);
    int mid=tr[k].l+tr[k].r>>1;
    if(mid>=l)query(k<<1,l,r);
    if(mid<r)query(k<<1|1,l,r);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;++i)cin>>a[i];
    build(1,1,n);
    while(m--){
        int op,l,r,k;
        cin>>op>>l>>r>>k;
        if(!op){
            update(1,l,r,k);
        }
        else{
            for(int i=0;i<K;++i)ans[i]=-inf;
            query(1,l,r);
            while(k&&ans[k-1]<cp)k--;
            cout<<ans[k-1]<<"\n";
            //for(int i=0;i<K;++i)cout<<ans[i]<<" ";
        }
    }
}

C++ 解法, 执行用时: 6783ms, 内存消耗: 205048K, 提交时间: 2021-06-13 15:48:17

#pragma GCC optimize(2)
#include <cstdio>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
const int M = 100005;
#define pii pair<int,int>
#define make make_pair
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,a[M];
struct zxy
{
	int lazy;vector<int> v;
	void clear() {lazy=0;v.clear();}
	zxy() {clear();}
	zxy(int r) {v.resize(1);v[0]=lazy=r;}
	void operator += (const zxy &b)
	{
		vector<int> tmp;
		int A=v.size(),B=b.v.size(),i=0,j=0;
		tmp.resize(A+B);
		while(i!=A && j!=B)
		{
			if(b.v[j]+lazy>v[i])
				tmp[i+j]=b.v[j]+lazy,j++;
			else
				tmp[i+j]=v[i],i++;
		}
		for(;i!=A;i++) tmp[i+j]=v[i];
		for(;j!=B;j++) tmp[i+j]=b.v[j]+lazy;
		v=tmp;lazy+=b.lazy;
		if(v.size()>100) v.resize(100);
	}
};
//
zxy mx[4*M],all[4*M],tag[4*M];
void up(int i)
{
	mx[i]=mx[i<<1];
	mx[i]+=mx[i<<1|1];
	all[i]=all[i<<1];
	all[i]+=all[i<<1|1]; 
}
void addtag(int x,zxy t)
{
	if(t.v.empty()) return ;
	priority_queue<pii> q;zxy tmp;
	for(int i=0;i<mx[x].v.size();i++)
		q.push(make(mx[x].v[i]+t.v[0],0));
	while(!q.empty() && tmp.v.size()<100)
	{
		pii u=q.top();q.pop();
		tmp.v.push_back(u.first);
		if(u.second<t.v.size()-1)
		{
			u.first-=t.v[u.second];
			u.first+=t.v[++u.second];
			q.push(u);
		}
	}
	all[x]+=tmp;
	for(int i=0;i<mx[x].v.size();i++)
		mx[x].v[i]+=t.lazy;
	tag[x]+=t;
}
void down(int i)
{
	addtag(i<<1,tag[i]);
	addtag(i<<1|1,tag[i]);
	tag[i].clear();
}
void build(int i,int l,int r)
{
	if(l==r)
	{
		mx[i]=all[i]=zxy(a[l]);
		mx[i].lazy=all[i].lazy=0;
		return ;
	}
	int mid=(l+r)>>1;
	build(i<<1,l,mid);
	build(i<<1|1,mid+1,r);
	up(i);
}
void upd(int i,int l,int r,int L,int R,int v)
{
	if(L>r || l>R) return ;
	if(L<=l && r<=R)
	{
		addtag(i,zxy(v));
		return ;
	}
	int mid=(l+r)>>1;down(i);
	upd(i<<1,l,mid,L,R,v);
	upd(i<<1|1,mid+1,r,L,R,v);
	up(i);
}
zxy ask(int i,int l,int r,int L,int R)
{
	if(L<=l && r<=R) return all[i];
	int mid=(l+r)>>1;down(i);
	if(mid>=R) return ask(i<<1,l,mid,L,R);
	if(mid<L) return ask(i<<1|1,mid+1,r,L,R);
	zxy tmp=ask(i<<1,l,mid,L,R);
	tmp+=ask(i<<1|1,mid+1,r,L,R);
	return tmp;
}
signed main()
{
	n=read();m=read();
	for(int i=1;i<=n;i++)
		a[i]=read();
	build(1,1,n);
	while(m--)
	{
		int op=read(),l=read(),r=read(),k=read();
		if(op==0) upd(1,1,n,l,r,k);
		else
		{
			zxy tmp=ask(1,1,n,l,r);
			int x=tmp.v.size();x=min(x,k);
			printf("%d\n",tmp.v[x-1]);
		}
	}
}

上一题