http://acm.hdu.edu.cn/showproblem.php?pid=5306 (题目连接)php
区间取$min$操做,区间求和操做,区间求最值操做。node
乱搞一通居然AC了= =,具体参考吉如一论文。蒯一发上来方便本身之后看嘿嘿。ios
对线段树中的每个节点除了维护区间最值和区间和之外,还要额外维护区间中的最大值$ma$,严格次大值$se$以及最大值个数$t$。优化
如今假设咱们要让区间$[L,R]$对$x$取$\min$,咱们先在线段树中定位这个区间,对定位的每个节点,咱们开始暴力搜索。搜索到的每个节点分三种状况进行讨论:ui
好暴力的作法,然而复杂度证实是玄学的势能分析,嗯我是实践派。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; }