1. 程式人生 > 實用技巧 >牛客小白月賽30 B.最好的寶石 (線段樹)

牛客小白月賽30 B.最好的寶石 (線段樹)

  • 題意:RT.
  • 題解:很明顯的線段樹維護區間最大值操作,但是我們同時還要維護最大值的個數,我們在build或者modify操作完子樹然後push_up的時候,我們先從兩個兒子取max更新父節點的最大值,然後再判斷父節點的最大值是否和兩個兒子相等,這樣我們就成功的維護了區間最大值的個數.剩下的就是線段樹的板子了.
  • 程式碼:
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

int n,m;
int w[N];

struct Node{
	int l,r;
	int v;
	int cnt;
}tr[N<<2];

void push_up(int u){
	tr[u].v=max(tr[u<<1].v,tr[u<<1|1].v);
	tr[u].cnt=0;
	if(tr[u].v==tr[u<<1].v) tr[u].cnt+=tr[u<<1].cnt;
	if(tr[u].v==tr[u<<1|1].v) tr[u].cnt+=tr[u<<1|1].cnt;
}

void build(int u,int l,int r){
	tr[u].l=l,tr[u].r=r,tr[u].cnt=0;
	if(l==r){
		tr[u].v=w[r];
		tr[u].cnt=1;
		return;
	}
	int mid=(l+r)>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	push_up(u);
}

void modify(int u,int x,int v){
	if(tr[u].l==x && tr[u].r==x){
		tr[u].v=v;
	}
	else{
		int mid=(tr[u].l+tr[u].r)>>1;
		if(x<=mid) modify(u<<1,x,v);
		else modify(u<<1|1,x,v);
		push_up(u);
	}
}

Node query(int u,int l,int r){
	if(tr[u].l>=l && tr[u].r<=r) return tr[u];
	else{
		int mid=(tr[u].l+tr[u].r)>>1;
		if(r<=mid) return query(u<<1,l,r);
		else if(l>mid) return query(u<<1|1,l,r);
		else{
			Node left=query(u<<1,l,r);
			Node right=query(u<<1|1,l,r);
			Node res;
		    res.v=max(left.v,right.v);
			res.cnt=0;
			if(res.v==left.v) res.cnt+=left.cnt;
			if(res.v==right.v) res.cnt+=right.cnt;
			return res;
		}
	}
}

int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>m;

	rep(i,1,n) cin>>w[i];

	build(1,1,n);

	while(m--){
		string op;
		cin>>op;
		if(op=="Change"){
			int x,y;
			cin>>x>>y;
			modify(1,x,y);
		}
		else{
			int l,r;
			cin>>l>>r;
			Node res=query(1,l,r);
			cout<<res.v<<' '<<res.cnt<<'\n';
		}
	}

    return 0;
}