zoukankan      html  css  js  c++  java
  • 「JOISC 2019 Day2」两道料理(差分+线段树)

    https://loj.ac/problem/3034

    (sa)表示a的前缀和,sb表示b的前缀和。

    (f[i][j])表示n个中的前i个、m个中的前j个完成了,最大的分数和。

    如果把第一维去掉,(f[i])是由(f[i-1])加上一些修改得到。

    那么就是先:

    1.(f[j]+=a[i](sa[i]+sb[j]<=s[i]))

    满足条件的j显然是一个前缀。

    2.(f[j]=max(f[j],f[i]-v[i]+v[j])(i<j))

    其中(v)是满足(sb[i]+sa[j]<=t[i])(q[i])的前缀和。

    对于第二个转移,考虑设(g[j]=f[j]-v[j]),不难发现,第二个转移在(g)上就是一个前缀max。

    那么变成在(g)上操作:
    1.(g[j]+=a[i](sa[i]+sb[j]<=s[i]))

    还是给(g)的前缀区间加上一个数。

    2.由于(a[i])的加入,会有一些新的(q[j])从v中剔除,v是前缀和,这个对v相当于后缀减,由于这个操作不会改变(f),所以相当于g的后缀加。

    3.对g取前缀max。

    注意1、2的操作都是区间加。

    考虑如何维护?先把1、2的区间加离散成若干个极长小区间,显然不管怎么操作,每一个小区间的相对大小不变,也就是依然满足非递减关系,只需要考虑小区间之间的前缀max。

    所以,左往右这样更新过去:

    比如有相邻的小区间([lx,rx])(ly,ry),若([lx,rx])的最大值大于([ly,ry])的开头,那么找到([ly,ry])开头相同的连续一段数,对这个进行区间加,以此类推。

    势能分析后复杂度是对的。

    Code

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int N = 1e6 + 5;
    
    int n, m;
    ll a[N], lima[N], p[N], sa[N];
    ll b[N], limb[N], q[N], sb[N], he[N];
    
    void Init() {
    	scanf("%d %d", &n, &m);
    	fo(i, 1, n) scanf("%lld %lld %lld", &a[i], &lima[i], &p[i]), sa[i] = sa[i - 1] + a[i];
    	fo(i, 1, m) scanf("%lld %lld %lld", &b[i], &limb[i], &q[i]), sb[i] = sb[i - 1] + b[i];
    }
    
    #define i0 i + i
    #define i1 i + i + 1
    ll t[N * 4], lz[N * 4]; int g[N * 4];
    ll pl, pr, px;
    void jia(int i, ll x) {
    	t[i] += x, lz[i] += x;
    }
    void down(int i) {
    	if(lz[i]) {
    		jia(i0, lz[i]);
    		jia(i1, lz[i]);
    		lz[i] = 0;
    	}
    }
    void add(int i, int x, int y) {
    	if(y < pl || x > pr) return;
    	if(x >= pl && y <= pr) { jia(i, px); return;}
    	int m = x + y >> 1; down(i);
    	add(i0, x, m); add(i1, m + 1, y);
    	t[i] = max(t[i0], t[i1]);
    	g[i] = (g[i0] & g[i1] & (t[i0] == t[i1]));
    }
    ll getv(int i, int x, int y, int l) {
    	if(g[i]) return t[i];
    	int m = x + y >> 1; down(i);
    	return l <= m ? getv(i0, x, m, l) : getv(i1, m + 1, y, l);
    }
    int py, pz; ll pk;
    void ft(int i, int x, int y) {
    	if(y < pl || x > pr || pz) return;
    	if(x >= pl && y <= pr && g[i]) {
    		if(t[i] != pk) { pz = 1; return;}
    		if(g[i]) { py = y; return;}
    	}
    	int m = x + y >> 1; down(i);
    	ft(i0, x, m);
    	ft(i1, m + 1, y);
    }
    
    int d[N]; ll h[N];
    int cmpd(int x, int y) {
    	return h[x]	< h[y];
    }
    
    int w[N * 8], w0;
    
    void cha(int x, int y, ll z) {
    	if(x > y) return;
    	pl = x, pr = y, px = z;
    	add(1, 0, m);
    	w[++ w0] = y; if(x) w[++ w0] = x - 1;
    }
    
    void dg(ll v, int x, int y) {
    	while(x <= y) {
    		ll v2 = getv(1, 0, m, x);
    		if(v <= v2) return;
    		pl = x, pr = y; py = 0, pz = 0; pk = v2;
    		ft(1, 0, m);
    		pl = x, pr = py; px = v - v2;
    		add(1, 0, m);
    		x = py + 1;
    	}
    }
    
    void premax() {
    	sort(w + 1, w + w0 + 1);
    	w0 = unique(w + 1, w + w0 + 1) - (w + 1);
    	fo(i, 1, w0) dg(getv(1, 0, m, w[i]), w[i] + 1, m);
    }
    
    void work() {
    	fo(i, 1, m * 4) g[i] = 1;
    	fo(i, 1, m) {
    		h[i] = limb[i] - sb[i];
    		d[i] = i;
    	}
    	sort(d + 1, d + m + 1, cmpd);
    	int l = 1;
    	while(l <= m && h[d[l]] < 0) l ++;
    	fo(i, 1, n) {
    		w0 = 0;
    		int as = -1;
    		for(int l = 0, r = m; l <= r; ) {
    			int mi = l + r >> 1;
    			if(sb[mi] <= lima[i] - sa[i]) as = mi, l = mi + 1; else r = mi - 1;
    		}
    		cha(0, as, p[i]);
    		while(l <= m && h[d[l]] < sa[i]) {
    			cha(d[l], m, q[d[l]]);
    			l ++;
    		}
    		premax();
    	}
    	ll ans = getv(1, 0, m, m);
    	while(l <= m) ans += q[d[l ++]];
    	pp("%lld
    ", ans);
    }
    
    int main() {
    	Init();
    	work();
    }
    
  • 相关阅读:
    jenkins构建完成后,执行的命令行的东西也会自动结束的解决办法
    解决ansible上传速度慢的问题
    uniq的坑坑
    tomcat问题
    R语言入门:对于boxplot()箱型图的直观理解
    R语言入门:条形图barplot()的绘制
    R语言入门:数据框的创建和访问
    Python当中的命令行参数sys.argv[]的使用方法
    R语言清除单个变量和全部变量
    linux下添加环境变量
  • 原文地址:https://www.cnblogs.com/coldchair/p/12431331.html
Copyright © 2011-2022 走看看