zoukankan      html  css  js  c++  java
  • BZOj 4540: [Hnoi2016]序列 [莫队 st表 预处理]

    4540: [Hnoi2016]序列

    题意:询问区间所有子串的最小值的和


    不强制在线当然上莫队啦
    但是没想出来,因为不知道该维护当前区间的什么信息,维护前后缀最小值的话不好做
    想到单调栈求一下,但是对于([l,r])还是可能有很多最小值,数据不随机的话会被卡

    预处理!!!
    预处理(l_i, r_i)以i为最小值的范围,(fl[i], fr[i])为从i开始 / 以i结尾的的前缀 / 后缀 最小值的和
    (fr[i] = (i - l_i + 1) * a_i + fr[i] - fr[l_i - 1])

    这是可减的!!!

    ([l, r] ightarrow [l, r+1]),求出(p=rmq(l, r+1)),对于(p-l+1)这些后缀最小值就是(a_p),剩下的直接用预处理的信息就行了 (fr[r] - fr[p])

    遇到不好处理的情况一定要想一下预处理 / DP

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=1e5+5;
    inline ll read() {
        char c=getchar(); ll x=0,f=1;
        while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
        while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    
    int n, a[N], Q, l, r, block, pos[N]; ll ans[N];
    struct meow{
    	int l, r, id;
    	bool operator <(const meow &a) const {return pos[l] == pos[a.l] ? r < a.r : pos[l] < pos[a.l];}
    } q[N];
    
    namespace cat {
    	int l[N], r[N], st[N], top; ll fl[N], fr[N]; 
    	int f[N][18], log[N];
    	inline int min(int x, int y) {return a[x]<a[y] ? x : y;}
    
    	void init() {
    		for(int i=1; i<=n; i++) {
    			while(top && a[ st[top] ] > a[i]) r[ st[top] ] = i-1, top--;
    			l[i] = st[top]+1;
    			st[++top] = i;
    		}
    		while(top) r[ st[top--] ] = n;
    		//for(int i=1; i<=n; i++) printf("%d  [%d, %d]
    ", i, l[i], r[i]);
    		for(int i=1; i<=n; i++) fr[i] = (ll) (i - l[i] + 1) * a[i] + fr[l[i] - 1];
    		for(int i=n; i>=1; i--) fl[i] = (ll) (r[i] - i + 1) * a[i] + fl[r[i] + 1];// printf("fl %d  %lld
    ",i,fl[i]); ;
    
    		for(int i=1; i<=n; i++) f[i][0] = i;
    		for(int j=1; j<=16; j++)
    			for(int i=1; i+(1<<j)-1 <= n; i++) 
    				f[i][j] = min(f[i][j-1], f[i+(1<<(j-1))][j-1]);// printf("f %d %d  %d
    ", i, j, f[i][j]);
    		log[1]=0; for(int i=2; i<=n; i++) log[i] = log[i>>1]+1;
    	}
    	inline int rmq(int l, int r) {
    		int t = log[r-l+1];
    		return min(f[l][t], f[r-(1<<t)+1][t]);
    	}
    
    	ll now;
    	inline void addr(int l, int r, ll flag) {
    		int p = rmq(l, r);
    		now += flag * ( (ll) (p-l+1) * a[p] + fr[r] - fr[p] );
    	}
    	inline void addl(int l, int r, ll flag) {
    		int p = rmq(l, r);
    		now += flag * ( (ll) (r-p+1) * a[p] + fl[l] - fl[p] );
    	}
    
    	void modui() {
    		sort(q+1, q+1+Q);
    		int l=1, r=0;
    		for(int i=1; i<=Q; i++) {
    			while(r < q[i].r) cat::addr(l, ++r, 1);
    			while(r > q[i].r) cat::addr(l, r--, -1);
    			while(l < q[i].l) cat::addl(l++, r, -1);
    			while(l > q[i].l) cat::addl(--l, r, 1);
    			ans[ q[i].id ] = now;
    		}
    	}
    }
    
    int main() {
    	freopen("in", "r", stdin);
    	n=read(); Q=read(); block = sqrt(n);
    	for(int i=1; i<=n; i++) a[i]=read(), pos[i] = (i-1)/block+1;
    	for(int i=1; i<=Q; i++) l=read(), r=read(), q[i] = (meow){l, r, i};
    	cat::init();
    	cat::modui();
    	for(int i=1; i<=Q; i++) printf("%lld
    ", ans[i]);
    }
    
    
  • 相关阅读:
    java中的静态代理、jdk动态代理和cglib动态代理
    第三方支付熟悉
    C#进制转换
    维翔主机asp主机使用遇到的问题及解决方案总结
    windows上JSP开发环境全搭建
    文件校验工具的开发及问题
    C#加密算法总结
    WampServer搭建php环境可能遇到的问题
    分分钟搭建自己的微信聊天机器人
    KindEditor编辑器在ASP.NET中的使用
  • 原文地址:https://www.cnblogs.com/candy99/p/6696247.html
Copyright © 2011-2022 走看看