【hdu5306】 Gorgeous Sequence

http://acm.hdu.edu.cn/showproblem.php?pid=5306 (題目連接)php

題意

  區間取$min$操做,區間求和操做,區間求最值操做。node

Solution

  亂搞一通居然AC了= =,具體參考吉如一論文。蒯一發上來方便本身之後看嘿嘿。ios

  對線段樹中的每個節點除了維護區間最值和區間和之外,還要額外維護區間中的最大值$ma$,嚴格次大值$se$以及最大值個數$t$。優化

  如今假設咱們要讓區間$[L,R]$對$x$取$\min$,咱們先在線段樹中定位這個區間,對定位的每個節點,咱們開始暴力搜索。搜索到的每個節點分三種狀況進行討論:ui

  1. 當$ma \leq x$時,顯然這一次修改不會對這個節點產生影響,直接退出。
  2. 當$se<x<ma$時,顯然這一次修改只會影響全部最大值,因此咱們把$sum$加上$t*(x-ma)$,把$ma$更新爲$x$,接着打上標記之後退出。
  3. 當$x \leq se$時,咱們沒法直接更新這個節點的信息,所以在這時,咱們對當前節點的左右兒子遞歸搜索。

  好暴力的作法,然而複雜度證實是玄學的勢能分析,嗯我是實踐派。spa

細節

  LL,也許你須要一發讀入優化= =。blog

代碼

// hdu5306
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf (1ll<<30)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;
inline int gi() {
	int x=0;char ch=getchar();
	while (ch<'0' || ch>'9') ch=getchar();
	while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
	return x;
}

const int maxn=1000010;
int n,m,a[maxn];
struct node {int l,r,t,ma,se,tag;LL s;}tr[maxn<<2];

void pushup(int k) {
	int l=k<<1,r=k<<1|1;
	if (tr[l].ma==tr[r].ma) {
		tr[k].ma=tr[l].ma,tr[k].t=tr[l].t+tr[r].t;
		tr[k].se=max(tr[l].se,tr[r].se);
	}
	else if (tr[l].ma<tr[r].ma) {
		tr[k].ma=tr[r].ma,tr[k].t=tr[r].t;
		tr[k].se=max(tr[l].ma,tr[r].se);
	}
	else {
		tr[k].ma=tr[l].ma,tr[k].t=tr[l].t;
		tr[k].se=max(tr[l].se,tr[r].ma);
	}
	tr[k].s=tr[l].s+tr[r].s;
}
void pushdown(int k) {
	int l=k<<1,r=k<<1|1,val=tr[k].ma;
	if (tr[l].se<val && tr[l].ma>val) {
		tr[l].s-=1LL*tr[l].t*(tr[l].ma-val);
		tr[l].ma=val;tr[l].tag=1;
	}
	if (tr[r].se<val && tr[r].ma>val) {
		tr[r].s-=1LL*tr[r].t*(tr[r].ma-val);
		tr[r].ma=val;tr[r].tag=1;
	}
	tr[k].tag=0;
}

void build(int k,int s,int t) {
	tr[k].l=s,tr[k].r=t;tr[k].se=-1;tr[k].tag=0;
	if (s==t) {tr[k].s=tr[k].ma=a[s];tr[k].t=1;return;}
	int mid=(s+t)>>1;
	build(k<<1,s,mid);
	build(k<<1|1,mid+1,t);
	pushup(k);
}
void modify(int k,int s,int t,int val) {
	int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
	if (l==s && r==t) {
		if (val>=tr[k].ma) return;
		if (tr[k].se<val) {
			tr[k].s-=1LL*tr[k].t*(tr[k].ma-val);
			tr[k].ma=val;tr[k].tag=1;
			return;
		}
	}
	if (tr[k].tag) pushdown(k);
	if (t<=mid) modify(k<<1,s,t,val);
	else if (s>mid) modify(k<<1|1,s,t,val);
	else modify(k<<1,s,mid,val),modify(k<<1|1,mid+1,t,val);
	pushup(k);
}
int querymx(int k,int s,int t) {
	int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
	if (l==s && r==t) return tr[k].ma;
	if (tr[k].tag) pushdown(k);
	if (t<=mid) return querymx(k<<1,s,t);
	else if (s>mid) return querymx(k<<1|1,s,t);
	else return max(querymx(k<<1,s,mid),querymx(k<<1|1,mid+1,t));
}
LL querysum(int k,int s,int t) {
	int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
	if (l==s && r==t) return tr[k].s;
	if (tr[k].tag) pushdown(k);
	if (t<=mid) return querysum(k<<1,s,t);
	else if (s>mid) return querysum(k<<1|1,s,t);
	else return querysum(k<<1,s,mid)+querysum(k<<1|1,mid+1,t);
}

int main() {
	int T=gi();
	while (T--) {
		n=gi(),m=gi();
		for (int i=1;i<=n;i++) a[i]=gi();
		build(1,1,n);
		for (int op,x,y,t,i=1;i<=m;i++) {
			op=gi(),x=gi(),y=gi();
			if (op==0) t=gi(),modify(1,x,y,t);
			if (op==1) printf("%d\n",querymx(1,x,y));
			if (op==2) printf("%lld\n",querysum(1,x,y));
		}
	}
	return 0;
}
相關文章
相關標籤/搜索