zoukankan      html  css  js  c++  java
  • P3168 [CQOI2015]任务查询系统

    题意描述:

    洛谷

    每一个任务有三个属性: (s,t,w) , 表示这个任务会在 (s-t) 这一段时间内运行,优先度为 (w) .

    (q) 组询问,每次询问你 第 (x) 秒运行的任务的优先度前 (k) 小的任务的优先度之和。

    数据范围: (n,mleq 10^5 , wleq 10^9)

    solution:

    有一个很 (naive) 的想法,对于每个任务把他 插入到 (s-t) 当中, 对于每一时刻开个权值线段树,权值为每个任务的优先度,每次询问就相当于在权值线段树上找前 (k) 小的数的和。

    暴力插的复杂度肯定不对,考虑怎么优化一下。

    我们维护的是每个时刻优先度为 (w) 的任务的个数,那么一个任务对 (s-t) 会有 (1) 的贡献。

    区间加 (1) ,很容易想到差分, 然后维护一下前缀和。

    拿主席树来维护一下,每次询问就在主席树上二分查找就好了。

    注意:每次修改都要新建一个版本,不然会导致节点的信息出错。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define int long long
    const int N = 2e5+10;
    const int inf = 1e7+10;
    int n,m,tot,s,t,p,x,a,b,c,k,cnt,last = 1,rt[N<<2],B[N];
    vector<pair<int,int> > v[N];
    struct Tree
    {
    	int lc,rc,siz,sum;
    }tr[40000000];
    inline int read()
    {
    	int s = 0,w = 1; char ch = getchar();
    	while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    	while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    	return s * w;
    }
    void up(int o)
    {
    	tr[o].siz = tr[tr[o].lc].siz + tr[tr[o].rc].siz;
    	tr[o].sum = tr[tr[o].lc].sum + tr[tr[o].rc].sum;
    }
    int insert(int &o,int last,int l,int r,int x,int val)
    {
    	o = ++tot;
    	if(l == r)
    	{
    		tr[o].siz = tr[last].siz + val;
    		tr[o].sum = tr[last].sum + val * B[l];
    		return o;
    	}
    	tr[o].lc = tr[last].lc;
    	tr[o].rc = tr[last].rc;
    	int mid = (l + r)>>1;
    	if(x <= mid) tr[o].lc = insert(tr[o].lc,tr[last].lc,l,mid,x,val);
    	if(x > mid) tr[o].rc = insert(tr[o].rc,tr[last].rc,mid+1,r,x,val);
    	up(o);
    	return o;
    }
    int query(int o,int l,int r,int k)
    {
    	if(!o) return 0;
    	if(l == r && tr[o].siz >= k) return k * B[l];
    	else if(l == r) return tr[o].sum;
    	if(tr[o].siz <= k) return tr[o].sum;
    	int mid = (l + r)>>1;
    	if(tr[tr[o].lc].siz >= k) return query(tr[o].lc,l,mid,k);
    	else return tr[tr[o].lc].sum + query(tr[o].rc,mid+1,r,k-tr[tr[o].lc].siz);
    }
    signed main()
    {
    	m = read(); n = read();
    	for(int i = 1; i <= m; i++)
    	{
    		s = read(); t = read(); p = read();
    		B[++cnt] = p;
    		v[s].push_back(make_pair(p,1));
    		v[t+1].push_back(make_pair(p,-1));
    	}
    	sort(B+1,B+cnt+1);
    	int num = unique(B+1,B+cnt+1)-B-1;
    	for(int i = 1; i <= n; i++) 
    	{
    		rt[i] = rt[i-1];
    		for(int j = 0; j < v[i].size(); j++)
    		{
    			int pos = lower_bound(B+1,B+num+1,v[i][j].first)-B;
    			rt[i] = insert(rt[i],rt[i],1,num,pos,v[i][j].second);
    		}
    	}
    	for(int i = 1; i <= n; i++)
    	{
    		x = read(); a = read(); b = read(); c = read();
    		k = 1 + (a * last % c + b) % c;
    		last = query(rt[x],1,num,k);
    		printf("%lld
    ",last);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    「Poetize7」Freda的访客
    「Poetize8」Divisible
    「Poetize5」Vani和Cl2捉迷藏
    1082. 员工的重要度
    1080. 最大的岛
    1079. 连续子串计数(经典)
    1078. 数组的度
    1071. 词典中最长的单词
    1068. 寻找数组的中心索引
    1062. 洪水填充(经典)
  • 原文地址:https://www.cnblogs.com/genshy/p/14387835.html
Copyright © 2011-2022 走看看