zoukankan      html  css  js  c++  java
  • 【hdu5306】 Gorgeous Sequence

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

    题意

      区间取$min$操作,区间求和操作,区间求最值操作。

    Solution

      乱搞一通竟然AC了= =,具体参考吉如一论文。蒯一发上来方便自己以后看嘿嘿。

      对线段树中的每一个节点除了维护区间最值和区间和以外,还要额外维护区间中的最大值$ma$,严格次大值$se$以及最大值个数$t$。

      现在假设我们要让区间$[L,R]$对$x$取$min$,我们先在线段树中定位这个区间,对定位的每一个节点,我们开始暴力搜索。搜索到的每一个节点分三种情况进行讨论:

    1. 当$ma leq x$时,显然这一次修改不会对这个节点产生影响,直接退出。
    2. 当$se<x<ma$时,显然这一次修改只会影响所有最大值,所以我们把$sum$加上$t*(x-ma)$,把$ma$更新为$x$,接着打上标记以后退出。
    3. 当$x leq se$时,我们无法直接更新这个节点的信息,因此在这时,我们对当前节点的左右儿子递归搜索。

      好暴力的做法,然而复杂度证明是玄学的势能分析,嗯我是实践派。

    细节

      LL,也许你需要一发读入优化= =。

    代码

    // 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
    ",querymx(1,x,y));
    			if (op==2) printf("%lld
    ",querysum(1,x,y));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    《将博客搬至CSDN》
    所谓找链表中点
    虚函数
    编辑距离
    数组移位
    DFA
    Single Number III
    XOR异或解惑
    First Bad Version
    while(!in.empty()) 和 while(in.size())
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6642226.html
Copyright © 2011-2022 走看看