zoukankan      html  css  js  c++  java
  • LOJ#6101. 「2017 山东二轮集训 Day1」第二题 题解

    题目链接

    按照最小值分治到两边,然后直接做即可。

    (Theta(nlog n)) , 如果 (Theta(n)) 建笛卡尔树可以做到 (Theta(n)) .

    code :

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    template <typename T> void read(T &x){
    	static char ch; x = 0,ch = getchar();
    	while (!isdigit(ch)) ch = getchar();
    	while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
    }
    inline void write(LL x){if (x > 9) write(x/10); putchar(x%10+'0'); }
    
    const int N = 100005;
    int n,k,a[N],Log[N],mn[N][20];
    struct data{
    	LL ans,r;
    	data(){ ans = r = 0; }
    	inline void add(LL v){ r += v; if (r > 0) ans += ceil(r * 1.0 / k),r -= ceil(r * 1.0 / k) * k;  }
    };
    inline int Mn(int l,int r){
    	static int t; t = Log[r-l+1],l = mn[l][t],r = mn[r-(1<<t)+1][t];
    	return a[l] < a[r] ? l : r;
    }
    data solve(int l,int r,int h){
    	if (l > r) return data();
    	if (l == r){ data tmp; tmp.add(a[l]-h); return tmp; }
    	int p = Mn(l,r); data tmp = solve(l,p-1,a[p]),R = solve(p+1,r,a[p]);
    	tmp.ans += R.ans,tmp.add(R.r),tmp.add((LL)(r-l+1)*(a[p]-h));
    	return tmp;
    }
    int main(){
    	int i,j,x,y;
    	read(n),read(k);
    	for (i = 1; i <= n; ++i) read(a[i]),mn[i][0] = i;
    	for (i = 1; i <= n; ++i){ Log[i] = Log[i-1]; if ((1<<Log[i]+1) < i) ++Log[i]; }
    	for (j = 1; j <= Log[n]; ++j) for (i = 1; i+(1<<j)-1 <= n; ++i)
    		x = mn[i][j-1],y = mn[i+(1<<j-1)][j-1],mn[i][j] = a[x] < a[y] ? x : y;
    	write(solve(1,n,0).ans),putchar('
    ');
    	return 0;
    }
    
  • 相关阅读:
    python操作csv,对比两个csv文件某列值
    监控端口和僵尸进程脚本
    openldap创建只读账号
    shell 判断文件内容是否改变
    golang调用shell命令标准输出阻塞管道
    fexpect 源码
    python pexpect 免交互自动恢复gitlab数据
    consul client agent 本地读取key value
    pip 安装三方库报超时
    微信小程序滚动tab的实现
  • 原文地址:https://www.cnblogs.com/s-r-f/p/13763647.html
Copyright © 2011-2022 走看看