zoukankan      html  css  js  c++  java
  • [CCC​2019] Tourism题解

    我们先考虑一下拿部分分:

    subtask1

    考虑因为 \(n < 2k\) ,那么我们的划分一定是从中间某个地方裁开,且满足 \(k\) 的条件的,我们发现当划分点在 \([n\ mod\ k,k]\)时满足条件,那么我们只需要维护一个前缀最大值和后缀最大值就好了。

    		for(int i = 1;i <= n;++i)
    		pre[i] = std::max(pre[i - 1],a[i]);
    		for(int i = n;i >= 1;--i)
    		s[i] = std::max(s[i + 1],a[i]);
    		ll ans = 0;
    		for(int i = n % k ;i <= k;++i)
    		ans = std::max(ans,1ll * pre[i] + s[i + 1]);
    		std::cout<<ans<<std::endl;
    

    subtask2

    我们发现这一档的分的关键是 \(k\) 很小,那么我们先轻松就能想到一个朴素的 \(dp\) ,我们设 \(f_i\) 为以 \(i\) 处为结尾的划分的答案最大值。为了满足转移次数最小,我们每次转移都要附上一个较大的代价 \(INF\)

    所以转移方程为 \(f_i = max_{j = max(0,i - k + 1)}(f_j + p(j + 1,i)) - INF,p(x,y) = max_{i = x} ^ y a_i\)

    最后我们发现转移次数我们是可以计算出来的,我们为 \(f_n\) 加上 \(\lfloor\frac{n}{k}\rfloor + [n \ mod\ k > 0] * INF\) 就好了。

    	for(int i = 1;i <= n;++i)
    	f[i] = -9e18;
    	// std::cout<<f[0]<<std::endl;
    	for(int i = 1;i <= n;++i){
    	ll ma = a[i];
    	ll m = std::max((ll)0,i - k + 1);
    	f[0] = 0;
    	for(int j = i;j >= m;--j){
    		ma = std::max(a[j],ma);
    		f[i] = std::max(1ll * f[j - 1] + ma - INF,f[i]);
    	}
    	// std::cout<<f[i] + (i / k + (i % k > 0)) * INF<<std::endl;
    	}
    	std::cout<<1ll * f[n] + 1ll * (n / k + (n % k > 0)) * INF<<std::endl;
    

    all subtask

    我们考虑 \(p(x,y)\) 是一个较难处理的点,我们可以使用单调栈来处理他。

    即我们依次向右扩展当前节点,并维护最大值的阶段。

    我们需要一个可以处理区间修改,区间查询最大值的数据结构,线段树。

    但是要注意一个最大值区间所对应的贡献区间要向左移一位。

    // Problem: P6647 [CCC 2019] Tourism
    // Contest: Luogu
    // URL: https://www.luogu.com.cn/problem/P6647
    // Memory Limit: 128 MB
    // Time Limit: 4000 ms
    // 
    // Powered by CP Editor (https://cpeditor.org)
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    #define N 1000005
    
    
    const ll INF = 1e12;
    ll n,k;
    int a[N];
    ll f[N];
    
    struct seg{int l,r;ll v,tag;}t[N * 6];
    
    ll st[N],tp;
    
    #define ls(x) (x << 1)
    #define rs(x) (x << 1 | 1)
    #define mid ((l + r) >> 1)
    
    inline void build(int u,int l,int r){
    	t[u].l = l;
    	t[u].r = r;
    	if(l == r)
    	return ;
    	build(ls(u),l,mid);
    	build(rs(u),mid + 1,r);
    }
    
    inline void up(int u){
    	t[u].v = std::max(t[ls(u)].v,t[rs(u)].v);
    }
    
    inline void push_down(int u){
    	if(t[u].tag){
    		t[ls(u)].tag += t[u].tag;
    		t[ls(u)].v += t[u].tag;
    		t[rs(u)].tag += t[u].tag;
    		t[rs(u)].v += t[u].tag;
    		t[u].tag = 0;
    	}
    }
    
    inline void md(int u,int tl,int tr,ll p){
    	// std::cout<<u<<" "<<t[u].l<<" "<<t[u].r<<" "<<tl<<" "<<tr<<" "<<p<<std::endl; 
    	ll l = t[u].l,r = t[u].r;
    	if(tl <= l && r <= tr){
    		t[u].v += p;
    		t[u].tag += p;
    		return ;
    	}
    	push_down(u);
    	if(tl <= mid)
    	md(ls(u),tl,tr,p);
    	if(tr > mid)
    	md(rs(u),tl,tr,p);
    	up(u);
    }
    
    inline ll find(int u,int tl,int tr){
    	ll ans = -9e18;
    	push_down(u);	
    	int l = t[u].l,r = t[u].r;
    	if(tl <= l && r <= tr)
    	return t[u].v;
    	if(tl <= mid)
    	ans = std::max(find(ls(u),tl,tr),ans);
    	if(tr > mid)
    	ans = std::max(find(rs(u),tl,tr),ans);
    	return ans;
    }
    
    int main(){
    	scanf("%lld%lld",&n,&k);
    	for(int i = 1;i <= n;++i)
    	scanf("%lld",&a[i]);
    	build(1,0,n);
    	for(int i = 1;i <= n;++i){
    		while(tp && a[st[tp]] <= a[i]){
    		if(a[st[tp]] == a[i]){--tp;continue;}
    		md(1,st[tp - 1],st[tp] - 1,a[i] - a[st[tp]]);//[st[tp] + 1,st[tp + 1]]向左移一位
    		--tp;			
    		}
    		st[++tp] = i;
    		md(1,i - 1,i - 1,f[i - 1] + a[i]);
    		ll ans = find(1,std::max(i - k,(ll)0),i - 1);
    		f[i] = ans - 1ll * INF;
    	}
    	// for(int i = 1;i <= n;++i)
    	// std::cout<<f[i] + (i - 1 + k) / k * INF<<std::endl; 
    	std::cout<<f[n] + (n - 1 + k) / k * INF;
    	
    }
    
  • 相关阅读:
    监控Nginx
    监控Tomcat
    监控memcache
    监控Redis
    14-SpringCloud Bus
    13-SpringCloud Config
    12-SpringCloud GateWay
    11-SpringCloud Hystrix
    10-SpringCloud OpenFeign
    09-SpringCloud Ribbon
  • 原文地址:https://www.cnblogs.com/dixiao/p/15019610.html
Copyright © 2011-2022 走看看