• UOJ46 【清华集训2014】玄学 【时间线段树】


    题目链接:UOJ

    这题的时间线段树非常的妙。

    对时间建立线段树,修改的时候在后面加,每当填满一个节点之后就合并进它的父亲。

    对于一个节点维护序列,发现这是一个分段函数,合并就是归并排序。于是就形成了差不多这样的一个结构。

    无标题

    查询的时候在分段函数上二分。

    因为每个断点至多被合并(log n)次,所以时间复杂度是(O(nlog^2n+mlog n))

    #include<bits/stdc++.h>
    #define Rint register int
    using namespace std;
    typedef long long LL;
    const int N = 100003;
    int id, tot, n, m, mod, val[N];
    struct Node {
    	int a, b, r;
    	inline Node(int _a = 0, int _b = 0, int _r = 0): a(_a), b(_b), r(_r){}
    	inline Node operator * (const Node &o) const {
    		return Node((LL) a * o.a % mod, ((LL) b * o.a + o.b) % mod, min(r, o.r));
    	}
    	inline bool operator < (const Node &o) const {
    		if(r != o.r) return r < o.r;
    		if(a != o.a) return a < o.a;
    		return b < o.b;
    	}
    };
    vector<Node> seg[N << 2];
    inline void add(int x, int l, int r, int a, int b){
    	seg[x].push_back(Node(1, 0, l - 1)); seg[x].push_back(Node(a, b, r)); if(r < n) seg[x].push_back(Node(1, 0, n));
    }
    inline void merge(vector<Node> &res, const vector<Node> A, const vector<Node> B){
    	int p = 0, q = 0;
    	while(p < A.size() && q < B.size()){
    		res.push_back(A[p] * B[q]);
    		if(A[p].r == B[q].r) ++ p, ++ q;
    		else if(A[p].r < B[q].r) ++ p;
    		else ++ q;
    	}
    }
    inline void change(int x, int L, int R, int l, int r, int a, int b){
    	if(L == R){add(x, l, r, a, b); return;}
    	int mid = L + R >> 1;
    	if(tot <= mid) change(x << 1, L, mid, l, r, a, b);
    	else change(x << 1 | 1, mid + 1, R, l, r, a, b);
    	if(tot == R) merge(seg[x], seg[x << 1], seg[x << 1 | 1]);
    }
    int ans;
    inline void query(int x, int L, int R, int l, int r, int k){
    	if(l <= L && R <= r){
    		auto it = lower_bound(seg[x].begin(), seg[x].end(), Node(0, 0, k));
    		ans = ((LL) ans * (it -> a) + (it -> b)) % mod;
    		return;
    	}
    	int mid = L + R >> 1;
    	if(l <= mid) query(x << 1, L, mid, l, r, k);
    	if(mid < r) query(x << 1 | 1, mid + 1, R, l, r, k);
    }
    int main(){
    	scanf("%d%d%d", &id, &n, &mod);
    	for(Rint i = 1;i <= n;i ++)
    		scanf("%d", val + i);
    	scanf("%d", &m);
    	for(Rint i = 1;i <= m;i ++){
    		int opt, l, r, a, b;
    		scanf("%d%d%d%d", &opt, &l, &r, &a);
    		if(id & 1) l ^= ans, r ^= ans;
    		if(opt == 1){
    			scanf("%d", &b); ++ tot;
    			change(1, 1, n, l, r, a, b);
    		} else if(opt == 2){
    			if(id & 1) a ^= ans;
    			ans = val[a];
    			query(1, 1, n, l, r, a);
    			printf("%d
    ", ans);
    		}
    	}
    }
    
  • 相关阅读:
    DevExpress GridControl使用方法
    DevExpress中,添加Winform窗体到DockPanel z
    取消默认 $ 定义
    五角星效果实现
    jquery的each函数的用法
    Object类型转换为long或者Long
    easyui datagrid 列排序
    redis.clients.jedis.exceptions.JedisDataException: WRONGTYPE Operation against a key holding the wrong kind of value
    DIV元素不换行
    JS 中div内容的显示和隐藏
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/11733197.html
Copyright © 2020-2023  润新知