zoukankan      html  css  js  c++  java
  • CQOI 2015 任务查询系统

    题意

    给定(m)个任务((l,r,p)),其中((l,r))代表这个任务将于时间([l,r])内进行,而(p)代表的是这个任务的优先级

    (n)个询问((x,k)),每次询问在时间点(x)进行的所有任务按优先级从小到大排序,前(k)个任务的优先级之和

    强制在线


    解法

    求前(k)个数的和,我们想到主席树

    区间覆盖问题,我们想到差分

    众所周知主席树运用了前缀和的思想,那么当然也可以进行差分

    那么这道题就是愉快的差分(+)主席树了

    把一个任务的((l,r))端点拆开,第(l)颗主席树的(p)位置加一,在第(r+1)颗主席树的(p)位置减一

    排序以后逐个加入,实际上就相当于在差分数组上求前缀和。具体实现上不用排序,会有点麻烦:用(vector)存储即可

    每次查询第(x)颗主席树的前(k)个元素之和即可

    但是我们会发现一个问题:如果在同一个位置我们进行了多次添加,此时主席树的根的标号与其所在的前缀可能是不对应的

    记录一个(id)代表每个前缀对应的实际根的编号即可


    代码

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    #define int long long
    
    #define Pii pair<int, int>
    #define x first
    #define y second
    
    void fast_IO();
    
    const int N = 2e5 + 10;
    
    int n, m, t;
    int it, rhs, lstans = 1;
    
    int s[N], id[N], rt[N];
    
    vector<Pii> vec[N];
    
    struct CTree {
    	
    	int sz;
    	int ls[N << 4], rs[N << 4], val[N << 4], sum[N << 4];
    	
    	void clear() { sz = 0; }
    	
    	int newnode() {
    		++sz;
    		ls[sz] = rs[sz] = val[sz] = sum[sz] = 0;
    		return sz;	
    	}
    	
    	void mkchain(int &x, int y, int l, int r, int k, int v) {
    		x = newnode();
    		ls[x] = ls[y], rs[x] = rs[y];
    		val[x] = val[y] + v, sum[x] = sum[y] + v * s[k];
    		if (l == r)	return;
    		int mid = l + r >> 1;	
    		if (k <= mid)
    			mkchain(ls[x], ls[y], l, mid, k, v);
    		else
    			mkchain(rs[x], rs[y], mid + 1, r, k, v);
    	}
    	
    	int query(int x, int l, int r, int k) {
    		int mid = l + r >> 1;
    		if (l == r)	return sum[x] / val[x] * k;
    		if (k <= val[ls[x]])
    			return query(ls[x], l, mid, k);
    		else if (k <= val[x])
    			return sum[ls[x]] + query(rs[x], mid + 1, r, k - val[ls[x]]);
    		else
    			return sum[x];
    	}
    		
    } tr;
    
    void discre() {
    	sort(s + 1, s + t + 1);
    	t = unique(s + 1, s + t + 1) - s - 1;
    }
    
    main() {
    	
    	fast_IO();
    	
    	cin >> n >> m;
    	
    	int x, a, b, c;
    	for (int i = 1; i <= n; ++i) {
    		cin >> a >> b >> c;
    		s[++t] = c, rhs = max(rhs, ++b);
    		vec[a].push_back(make_pair(c, 1));	
    		vec[b].push_back(make_pair(c, -1));
    	}
    	
    	discre();
    	
    	for (int i = 1; i <= rhs; ++i) {
    		if (vec[i].empty()) {
    			id[i] = ++it;
    			rt[it] = rt[it - 1];
    			continue;	
    		}
    		int sz = vec[i].size();
    		id[i] = it + sz;
    		for (int j = 0; j < sz; ++j) {
    			int p = lower_bound(s + 1, s + t + 1, vec[i][j].x) - s;
    			++it;
    			tr.mkchain(rt[it], rt[it - 1], 1, t, p, vec[i][j].y);
    		}
    	}
    	
    	for (int i = 1; i <= m; ++i) {
    		cin >> x >> a >> b >> c;
    		a = 1 + (a * lstans + b) % c;
    		cout << (lstans = tr.query(rt[id[x]], 1, t, a)) << endl;
    	}
    	
    	return 0;
    }
    
    void fast_IO() {
    	ios :: sync_with_stdio(false);
    	cin.tie(NULL), cout.tie(NULL);
    }
    
  • 相关阅读:
    charles 安装、破解、简单介绍
    8、postman中 转码生成python-requests接口请求代码,并定义一个获取及请求的方法
    json 序列化和反序列化(针对python数据类型)
    leetcode 35.搜索插入位置
    leetcode 27.移除元素
    js 中的数组方法
    js判断小数点后几位小数
    leetcode 15.三数之和
    leetcode 1.两数之和
    leetcode 680.验证回文字符串
  • 原文地址:https://www.cnblogs.com/VeniVidiVici/p/11474589.html
Copyright © 2011-2022 走看看