zoukankan      html  css  js  c++  java
  • BZOJ3932 [CQOI2015]任务查询系统 主席树

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ3932


    题意概括

      电脑有N个任务需要执行,任务i在li到ri时正在工作,优先级为p。 现在给出M个询问,每个询问给出一个时间点xi和一个数ki。问在xi这个时间点时,所有正在工作的任务中优先级从小到大排列,前ki个的优先级之和是多少。 强制在线。 N<=100 000,M<=100 000


    题解

      用差分的思想,在Li的地方加,在Ri的地方减。

      然后就是裸的主席树。

      有坑。

      这题细节丧病。

      首先,我把n和m反着写,然后还以为时间点是n(我的n),事实上是我的m。

      其次,还会出现同一个时间点多个事件,要考虑,所以对于长度为1的区间,要sum/size*k

      当然,事情还没有结束。

      size有可能是0,要特判。


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const int N=100005;
    int n,m,Ha[N],hs;
    vector <int> tz[N];
    struct Task{
    	int L,R,P;
    	void Read(){
    		scanf("%d%d%d",&L,&R,&P);
    	}
    }t[N];
    void LSH(){
    	int hs_=1;
    	sort(Ha+1,Ha+hs+1);
    	for (int i=2;i<=hs;i++)
    		if (Ha[i]!=Ha[i-1])
    			Ha[++hs_]=Ha[i];
    	hs=hs_;
    }
    const int S=N*4*20;
    int ls[S],rs[S],size[S],total,root[N];
    LL sum[S];
    int find(int v){
    	return lower_bound(Ha+1,Ha+hs+1,v)-Ha;
    }
    void build(int &rt,int L,int R){
    	rt=++total;
    	if (L==R)
    		return;
    	int mid=(L+R)>>1;
    	build(ls[rt],L,mid);
    	build(rs[rt],mid+1,R);
    }
    void add(int prt,int &rt,int L,int R,int pos,LL v,int op){
    	if (!rt||rt==prt)
    		rt=++total,sum[rt]=sum[prt],size[rt]=size[prt];
    	sum[rt]+=v,size[rt]+=op;
    	if (L==R)
    		return;
    	int mid=(L+R)>>1;
    	if (!ls[rt])
    		ls[rt]=ls[prt];
    	if (!rs[rt])
    		rs[rt]=rs[prt];
    	if (pos<=mid)
    		add(ls[prt],ls[rt],L,mid,pos,v,op);
    	else
    		add(rs[prt],rs[rt],mid+1,R,pos,v,op);
    }
    LL query(int rt,int L,int R,int k){
    	if (L==R){
    		k=min(k,size[rt]);
    		if (size[rt]==0)
    			return 0;
    		return sum[rt]*k/size[rt];
    	}
    	int Lz=size[ls[rt]];
    	int mid=(L+R)>>1;
    	if (Lz>=k)
    		return query(ls[rt],L,mid,k);
    	else
    		return sum[ls[rt]]+query(rs[rt],mid+1,R,k-Lz);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++){
    		t[i].Read();
    		Ha[i]=t[i].P;
    	}
    	hs=n;
    	LSH();
    	for (int i=1;i<=m+1;i++)
    		tz[i].clear();
    	for (int i=1;i<=n;i++){
    		tz[t[i].L].push_back(i);
    		tz[t[i].R+1].push_back(i);
    		t[i].P=find(t[i].P);
    	}
    	total=0;
    	build(root[0],1,hs);
    	for (int i=1;i<=m;i++){
    		root[i]=root[i-1];
    		for (int j=0;j<tz[i].size();j++){
    			int k=tz[i][j];
    			if (t[k].L==i)
    				add(root[i-1],root[i],1,hs,t[k].P,Ha[t[k].P],1);
    			else
    				add(root[i-1],root[i],1,hs,t[k].P,-Ha[t[k].P],-1);
    		}
    	}
    	LL pre=1;
    	for (int i=1;i<=m;i++){
    		int x,A,B,C,k;
    		scanf("%d%d%d%d",&x,&A,&B,&C);
    		k=(pre*A+B)%C+1;
    		printf("%lld
    ",pre=query(root[x],1,hs,k));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    简单的模板解析函数
    HTML通过事件传递参数到js 二 event
    HTML通过事件传递参数到js一
    通过this获取当前点击选项相关数据
    LeetCode 20. 有效的括号(Valid Parentheses)
    LeetCode 459. 重复的子字符串(Repeated Substring Pattern)
    LeetCode 14. 最长公共前缀(Longest Common Prefix)
    LeetCode 168. Excel表列名称(Excel Sheet Column Title)
    LeetCode 171. Excel表列序号(Excel Sheet Column Number) 22
    LeetCode 665. 非递减数列(Non-decreasing Array)
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ3932.html
Copyright © 2011-2022 走看看