• JZOJ 5750. 青青草原播种计划 (小性质+线段树)


    Description:


    (1 le n, Q le 5e5)

    题解:

    这题唯一的难度就是如何知道最小不可询问子草原绿值。

    这个相当于问:有一堆数,每个可以用一次或不用,问最小凑不出来的自然数是多少。

    首先把这些数排序,假设当前的答案是(p),初值(=1)

    从小到大加入每个数(x),若(x le p),则(p+=x),否则答案就是(p)了。

    这个贪心很妙。

    我们可以把它改成:每次求(p)以内的数的和,看看和有没有(>p),若(>p),则继续,否则答案就是(p)

    因为每次(p)都会至少(+=lp(上次的p)),所以复杂度相当于斐波拉契数列,近似为(log)

    在线段树上实现这个就乘个(log)

    其它的就是可持久化线段树,以及线段树合并一类简单问题。

    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 = 5e5 + 5;
    
    int n, Q;
    int op, x, y;
    int rt[N];
    
    #define pii pair<int, int>
    multiset<pii> srt[N];
    
    #define i0 t[i].l
    #define i1 t[i].r
    struct tree {
    	int l, r, x;
    	ll s;
    } t[N * 35]; int tt;
    
    int pl, pr, px;
    
    void upd(int i) {
    	t[i].x = min(t[i0].x, t[i1].x);
    	t[i].s = t[i0].s + t[i1].s;
    }
    
    void add(int &i, int x, int y) {
    	if(y < pl || x > pr) return;
    	t[++ tt] = t[i], i = tt;
    	if(x == y) {
    		t[i].x += px;
    		if(t[i].x < 0) t[i].x = 0;
    		t[i].s = (ll) t[i].x * x;
    		return;
    	}
    	int m = x + y >> 1;
    	add(i0, x, m); add(i1, m + 1, y);
    	upd(i);
    }
    
    int mer(int i, int j, int x, int y) {
    	if(!i || !j) return i + j;
    	int k = ++ tt;
    	if(x == y) {
    		t[k].x = t[i].x + t[j].x;
    		t[k].s = t[i].s + t[j].s;
    		return k;
    	}
    	int m = x + y >> 1;
    	t[k].l = mer(t[i].l, t[j].l, x, m);
    	t[k].r = mer(t[i].r, t[j].r, m + 1, y);
    	upd(k); return k;
    }
    
    void ef(int i, int x, int y) {
    	if(t[i].x > 0) return;
    	if(x == y) { px = x; return;}
    	int m = x + y >> 1;
    	ef(i0, x, m);
    	if(px > m) ef(i1, m + 1, y);
    }
    
    ll py;
    
    void ft(int i, int x, int y) {
    	if(y < pl || x > pr || !i) return;
    	if(x >= pl && y <= pr) {
    		py += t[i].s; return;
    	}
    	int m = x + y >> 1;
    	ft(i0, x, m); ft(i1, m + 1, y);
    }
    
    int ans;
    
    void qry(int i) {
    	px = 5e5 + 1;
    	ef(i, 1, 5e5);
    	ans = px;
    	pp("%d ", ans);
    	
    	ll lp = 0, p = 1;
    	while(1) {
    		pl = lp + 1, pr = p, py = 0;
    		ft(i, 1, 5e5);
    		if(py == 0) break;
    		lp = p, p += py;	
    	}
    	pp("%lld
    ", p);
    }
    
    void dg(int i, int x, int y) {
    	if(!t[i].s) return;
    	if(x == y) {
    		fo(j, 1, t[i].x) pp("%d ", x);
    		return;
    	}
    	int m = x + y >> 1;
    	dg(i0, x, m); dg(i1, m + 1, y);
    }
    
    int main() {
    	freopen("forgive.in", "r", stdin);
    	freopen("forgive.out", "w", stdout);
    	scanf("%d %d", &n, &Q);
    	fo(ii, 1, Q) {
    		scanf("%d", &op);
    		if(op == 1 || op == 2) {
    			scanf("%d %d", &x, &y);
    			x = (x + ans - 1) % n + 1;
    			pl = pr = y; px = op == 1 ? 1 : -1;
    			add(rt[x], 1, 5e5);
    			srt[x].insert(pii(ii, rt[x]));
    		} else
    		if(op == 3) {
    			scanf("%d %d", &x, &y);
    			x = (x + ans - 1) % n + 1;
    			y = (y + ans - 1) % n + 1;
    			if(x == y) continue;
    			rt[x] = mer(rt[x], rt[y], 1, 5e5);
    			rt[y] = 0;
    			srt[x].insert(pii(ii, rt[x]));
    			srt[y].insert(pii(ii, rt[y]));
    		} else
    		if(op == 4) {
    			scanf("%d", &x);
    			x = (x + ans - 1) % n + 1;
    			qry(rt[x]);
    		} else {
    			scanf("%d %d", &x, &y);
    			x = (x + ans - 1) % n + 1;
    			pii p;
    			if(srt[x].empty() || (*srt[x].begin()).first >= y) {
    				p = pii(0, 0);
    			} else p = (*--srt[x].lower_bound(pii(y, 0)));
    			qry(p.second);
    		}
    	}
    	fo(i, 1, n) {
    		dg(rt[i], 1, 5e5);
    		pp("0
    ");
    	}
    }
    
  • 相关阅读:
    Java Message Service学习(一)
    二叉树的层序遍历算法实现
    二叉树的操作之统计二叉树中节点的个数
    java.uti.Random类nextInt方法中随机数种子为47的奇怪问题
    最大子序列和问题
    参数对象Struts2中Action的属性接收参数
    方法字段[C# 基础知识系列]专题二:委托的本质论
    struts2属性Struts2中属性接收参数中文问题和简单数据验证
    权限检查联系人ProfileProvider
    最小较小codeforces 2B The least round way
  • 原文地址:https://www.cnblogs.com/coldchair/p/12860449.html
Copyright © 2020-2023  润新知