zoukankan      html  css  js  c++  java
  • 「JOISC 2019 Day3」穿越时空 Bitaro(差分+线段树维护分段函数):

    https://loj.ac/problem/3038

    题解:

    只考虑从左往右是怎么做的,从右往左同理。

    如果是x->y,那么最优的方案肯定是一直往右走。

    考虑从x->x+1,时间会加1,这让我们非常不爽。

    不妨把(l[i]-=i,r[i]-=i),这样就不用考虑走边带来的时间+1(硬要考虑也是行的)。

    于是每题变成,一个矩阵,第(i)列可以走([l[i],r[i]))行,列与列之间向上走没有代价,向下走一个有一个代价。

    当只经过一列时,不难发现代价和终点都是三段关于起点的一次函数。

    事实上,通过归纳,可以得到,当我们经过一个区间的列时,代价和终点都是三段分段函数。

    那么我们套个线段树,线段树上就暴力维护这个分段函数就好了,我写的比较丑,有一个3*3=9的大常数。

    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 = 3e5 + 5;
    
    const ll inf = 2e9;
    
    struct P {
    	ll x, y;
    	P(ll _x = 0, ll _y = 0) {
    		x = _x, y = _y;
    	}
    };
    
    bool operator == (P a, P b) {
    	return a.x == b.x && a.y == b.y;
    }
    
    ll val(P a, ll b) {
    	return a.x * b + a.y;
    }
    
    struct Q {
    	P a, b, c;
    };
    
    int n, q, op;
    ll l[N], r[N], x, y, z, w;
    
    #define i0 i + i
    #define i1 i + i + 1
    Q f[N * 4][3], g[N * 4][3]; int pl, pr;
    
    Q d[10]; int d0;
    void mer(Q a, Q b) {
    	if(a.a.x > a.a.y) return;
    	if(b.a.x > b.a.y) return;
    	if(a.b.x == 0) {
    		if(!(a.b.y >= b.a.x && a.b.y <= b.a.y)) return;
    		if(b.b.x == 0) {
    			a.c.y = a.c.y + val(b.c, a.b.y);
    			a.b = b.b;
    			d[++ d0] = a;
    		} else {
    			d[++ d0] = a;
    		}
    	} else {
    		ll l = max(a.a.x, b.a.x), r = min(a.a.y, b.a.y);
    		if(l > r) return;
    		a.a = P(l, r);
    		if(b.b.x == 0) {
    			a.b = b.b;
    			a.c = b.c;
    			d[++ d0] = a;
    		} else {
    			d[++ d0] = a;
    		}
    	}
    }
    Q d2[10];
    void dod() {
    	fo(i, 1, d0) d2[i] = d[i];
    	int D = d0; d0 = 0;
    	fo(i, 1, D) {
    		if(!d0 || !(d2[i].b == d[d0].b && d2[i].c == d[d0].c)) {
    			d[++ d0] = d2[i];
    		} else {
    			d[d0].a.y = d2[i].a.y;
    		}
    	}
    }
    
    void upd(Q *a, Q *b, Q *c) {
    	d0 = 0;
    	fo(i, 0, 2) fo(j, 0, 2) mer(b[i], c[j]);
    	dod();
    	fo(i, 1, d0) a[i - 1] = d[i];
    	fo(i, d0, 2) a[i].a = P(1, 0);
    }
    
    void add(int i, int x, int y) {
    	if(x == y) {
    		int u = l[x] - x, v = r[x] - x - 1;
    		f[i][0] = (Q) {P(-inf, u - 1), P(0, u), P(0, 0)};
    		f[i][1] = (Q) {P(u, v), P(1, 0), P(0, 0)};
    		f[i][2] = (Q) {P(v + 1, inf), P(0, v), P(1, -v)};
    		
    		u = l[x] + x, v = r[x] + x - 1;
    		g[i][0] = (Q) {P(-inf, u - 1), P(0, u), P(0, 0)};
    		g[i][1] = (Q) {P(u, v), P(1, 0), P(0, 0)};
    		g[i][2] = (Q) {P(v + 1, inf), P(0, v), P(1, -v)};
    		return;
    	}
    	int m = x + y >> 1;
    	if(pl <= m) add(i0, x, m); else add(i1, m + 1, y);
    	upd(f[i], f[i0], f[i1]);
    	upd(g[i], g[i1], g[i0]);
    }
    Q px[3]; int py;
    void ft(int i, int x, int y) {
    	if(y < pl || x > pr) return;
    	if(x >= pl && y <= pr) {
    		upd(px, px, py ? g[i] : f[i]);
    		return;
    	}
    	int m = x + y >> 1;
    	if(py) ft(i1, m + 1, y), ft(i0, x, m); else
    		ft(i0, x, m), ft(i1, m + 1, y);
    }
    
    int main() {
    	scanf("%d %d", &n, &q);
    	n --;
    	fo(i, 1, n) {
    		scanf("%d %d", &l[i], &r[i]);
    		pl = pr = i, add(1, 1, n);
    	}
    	fo(ii, 1, q) {
    		scanf("%d %lld %lld %lld", &op, &x, &y, &z);
    		if(op == 1) {
    			l[x] = y, r[x] = z;
    			pl = pr = x;
    			add(1, 1, n);
    		} else {
    			scanf("%lld", &w);
    			px[0] = (Q) {P(-inf, inf), P(1, 0), P(0, 0)};
    			px[1].a = px[2].a = P(1, 0);
    			ll ans = 0;
    			if(x <= z) {
    				y -= x, w -= z;
    				pl = x, pr = z - 1; py = 0; ft(1, 1, n);
    			} else {
    				y += x - 1, w += z - 1;
    				pl = z, pr = x - 1; py = 1; ft(1, 1, n);
    			}
    			fo(j, 0, 2) if(y >= px[j].a.x && y <= px[j].a.y) {
    				ans += val(px[j].c, y);
    				y = val(px[j].b, y);
    				break;
    			}
    			ans += max(0ll, y - w);
    			pp("%lld
    ", ans);
    		}
    	}
    }
    
  • 相关阅读:
    Android 5.0以下系统支持TLS 1.1/1.2协议版本
    Java & Android未捕获异常处理机制
    Oppo Reno2 不允许安装非正式签名应用
    Android ADB 实用总结
    Android Studio中的非项目文件及项目目录下的全局搜索
    Android开发中网络代理设置实用总结
    基于时间偏差思路下的时间周期度量
    nodejs anywhere 搭建本地静态文件服务
    Android 支持库迁移到AndroidX
    项目Gradle版本从4.4升级到4.6
  • 原文地址:https://www.cnblogs.com/coldchair/p/12456872.html
Copyright © 2011-2022 走看看