列表

详情


NC206081. 最简单的一道题

描述

有一个 n 个数的数组,代表 n 栋建筑,有如下两种操作:
1. 修改:区间 l 到 r 内的建筑增高 k(正整数)
2. 查询:对于某个位置 x,求 y 的数目( ,且对于位置 y ,位置 x 到位置 y 的这段区间的最小值是位置 y 的值)

输入描述

第一行两个数字 n 和 m , 表示数字个数和操作个数
第二行 n 个数字,表示建筑高度
后面 m 行指令:
或者:
数据范围:

输出描述

对于每个查询,输出答案,每个答案一行

示例1

输入:

5 5
1 2 3 4 3
q 3
c 1 3 3
q 2
c 5 5 4
q 5

输出:

1
2
0

原站题解

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

C++14(g++5.4) 解法, 执行用时: 398ms, 内存消耗: 18408K, 提交时间: 2020-05-23 20:33:00

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define fi first
#define se second
#define debug(x) cerr << #x << " " << x << '\n'
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pli = pair<ll,int>;
const int INF = 0x3f3f3f3f, N = 2e5 + 5;
const ll LINF = 1e18 + 5;
constexpr int mod = 1e9 + 7;
int a[N];
int n, m, pos[N];
vector<int> vec;
namespace SegTree
{
	#define ls (p<<1)
	#define rs (p<<1|1)
	struct seg
	{
		int l, r, len;
		ll mn, tag;
	}t[N<<2];
	void setval(int p, ll v)
	{
		t[p].mn += v;
		t[p].tag += v;
	}
	void pushdown(int p)
	{
		setval(ls, t[p].tag); setval(rs, t[p].tag);
		t[p].tag = 0;
	}
	int ask2(int p, int x)
	{
		int l = t[p].l, r = t[p].r;
		if(l==r) return t[p].mn;
		if(t[p].tag) pushdown(p);
		int mid = (l+r)>>1;
		if(x<=mid) return ask2(ls, x);
		else return ask2(rs, x);
	}
	int merge(int v, int p)
	{
		int l = t[p].l, r = t[p].r;
		if(t[p].mn>v) return 0;
		//if(ask2(1, l)<=v) return t[p].len;
		if(l==r) return t[p].mn<=v;
		if(t[p].tag) pushdown(p);
		if(t[ls].mn>v) return merge(v, rs);
		else return merge(v, ls) + t[p].len - t[ls].len;
	}
	void pushup(int p)
	{
		t[p].mn = min(t[ls].mn, t[rs].mn);
		t[p].len = t[ls].len + merge(t[ls].mn, rs);
	}
	void build(int p, int l, int r)
	{
		t[p].l = l, t[p].r = r;
		if(l==r) 
		{
			t[p].mn = a[l];
			t[p].len = 1;
			pos[l] = p;
			return;
		}
		int mid = (l+r)>>1;
		build(ls, l, mid); build(rs, mid+1, r);
		pushup(p);
	}
	void upd(int p, int x, int y, int v)
	{
		int l = t[p].l, r = t[p].r;
		if(l>=x && r<=y) 
		{
			setval(p, v);
			return;
		}
		if(t[p].tag) pushdown(p);
		int mid = (l+r)>>1;
		if(x<=mid) upd(ls, x, y, v);
		if(y>mid) upd(rs, x, y, v);
		pushup(p);
	}
	void ask(int p, int x, int y)
	{
		int l = t[p].l, r = t[p].r;
		if(l>=x && r<=y) 
		{
			vec.pb(p);
			return;
		}
		if(t[p].tag) pushdown(p);
		int mid = (l+r)>>1;
		if(x<=mid) ask(ls, x, y);
		if(y>mid) ask(rs, x, y);
	}
	#undef ls
	#undef rs
}
using namespace SegTree;
char op[2];
int main()
{
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++) scanf("%d", a+i);
	build(1, 1, n);
	for(int i=1; i<=m; i++)
	{	
		scanf("%s", op);
		if(op[0]=='c')
		{
			int l, r, k;
			scanf("%d%d%d", &l, &r, &k);
			upd(1, l, r, k);
		}
		else
		{
			int x;
			scanf("%d", &x);
			vec.clear();
			ask(1, x, n);
			int ans = t[vec[0]].len;
			ll mn = t[vec[0]].mn;
			for(int i=1; i<sz(vec); i++)
			{
				ans += merge(mn, vec[i]);
				mn = min(mn, t[vec[i]].mn);
			}
			printf("%d\n", ans-1);
		}
	}
	return 0;
}

C++ 解法, 执行用时: 294ms, 内存消耗: 6292K, 提交时间: 2021-05-28 19:10:47

#include <iostream>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
int n,m;
int a[N];
#define mid (l+r>>1)
#define ls o<<1
#define rs o<<1|1
int t[N<<2],laz[N<<2];
int g[N<<2];
void pd(int o){
  if(laz[o]){
    laz[ls]+=laz[o];
    laz[rs]+=laz[o];
    t[ls]+=laz[o];
    t[rs]+=laz[o];
    laz[o]=0;
  }
}
int merge(int o,int  l,int r,int x){
  //找到这个区间
  if(l==r)return t[o]<=x;
  pd(o);
  if(t[o]>x)return 0;
  if(t[ls]>x)return merge(rs,mid+1,r,x);
  return merge(ls,l,mid,x)+g[o]-g[ls];
}
void push_up(int o,int l,int r){
  t[o]=min(t[ls],t[rs]);
  g[o]=g[ls]+merge(rs,mid+1,r,t[ls]);//
}
void build(int o,int l,int r){
  if(l==r){
    t[o]=a[l];
    g[o]=1;
    return ;
  }
  build(ls,l,mid);
  build(rs,mid+1,r);
  push_up(o,l,r);
}
 
void up(int o,int l,int r,int x,int y,int d){
  if(l>=x&&r<=y){
    laz[o]+=d;
    t[o]+=d;//
    return ;
  }
  pd(o);
  if(x<=mid)up(ls,l,mid,x,y,d);
  if(y>mid)up(rs,mid+1,r,x,y,d);
  push_up(o,l,r);
}
int getx(int o,int l,int r,int x){
  if(l==r)return t[o];
  pd(o);
  int ans;
  if(x<=mid)ans=getx(ls,l,mid,x);
  else ans=getx(rs,mid+1,r,x);
  push_up(o,l,r);
  return ans;
}
int get(int o,int l,int r,int x,int y,int &val){
  if(l>=x&&r<=y){
    int ans=merge(o,l,r,val);
    val=min(val,t[o]);
    return ans;
  }
  pd(o);
  int ans=0;
  if(x<=mid)ans+=get(ls,l,mid,x,y,val);
  if(y>mid)ans+=get(rs,mid+1,r,x,y,val);
  push_up(o,l,r);
  return ans;
}
int main() {
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++)scanf("%d",a+i);
  build(1,1,n);
  for(int i=1;i<=m;i++){
    char x;
    scanf(" %c",&x);
    if(x=='c'){
      int l,r,k;
      scanf("%d%d%d",&l,&r,&k);
      up(1,1,n,l,r,k);
    }else{
      int x;
      scanf("%d",&x);
      int d=getx(1,1,n,x);//
      if(x+1<=n)printf("%d\n",get(1,1,n,x+1,n,d));
      else puts("0");
    }
  }
  return 0;
}

上一题