• 【BZOJ3932】任务查询系统(主席树)


    【BZOJ3923】任务查询系统(主席树)

    题面

    Description

    最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。超级计算机中的
    任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行
    ),其优先级为Pi。同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同。调度系统会经常向
    查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个
    )的优先级之和是多少。特别的,如果Ki大于第Xi秒正在运行的任务总数,则直接回答第Xi秒正在运行的任务优先
    级之和。上述所有参数均为整数,时间的范围在1到n之间(包含1和n)。

    Input

    输入文件第一行包含两个空格分开的正整数m和n,分别表示任务总数和时间范围。接下来m行,每行包含三个空格
    分开的正整数Si、Ei和Pi(Si≤Ei),描述一个任务。接下来n行,每行包含四个空格分开的整数Xi、Ai、Bi和Ci,
    描述一次查询。查询的参数Ki需要由公式 Ki=1+(Ai*Pre+Bi) mod Ci计算得到。其中Pre表示上一次查询的结果,
    对于第一次查询,Pre=1。

    Output

    输出共n行,每行一个整数,表示查询结果。

    Sample Input

    4 3

    1 2 6

    2 3 3

    1 3 2

    3 3 4

    3 1 3 2

    1 1 3 4

    2 2 4 3

    Sample Output

    2

    8

    11

    HINT

    样例解释

    K1 = (1*1+3)%2+1 = 1

    K2 = (1*2+3)%4+1 = 2

    K3 = (2*8+4)%3+1 = 3

    对于100%的数据,1≤m,n,Si,Ei,Ci≤100000,0≤Ai,Bi≤100000,1≤Pi≤10000000,Xi为1到n的一个排列

    题解

    真是一道好题
    对于一个任务出现的时间
    拆为:S时刻出现,E+1时刻消失
    那么,以优先级为权值,构建主席树
    把任务拆开后,很容易利用主席树求前缀和
    所以第K大也就很容易的求出来了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAX 120000
    #define ll long long
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    struct Event
    {
    	int t,p,w;
    }e[MAX<<2];
    struct Node
    {
    	int ls,rs;
    	int v;
    	long long s;
    }t[MAX<<5];
    int n,m,tot,sum,S[MAX],cnt,rt[MAX];
    bool operator<(Event a,Event b){return a.t<b.t;}
    void Build(int &now,int l,int r)
    {
    	now=++tot;
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	Build(t[now].ls,l,mid);
    	Build(t[now].rs,mid+1,r);
    }
    void Modify(int &now,int ff,int l,int r,int pos,int w)
    {
    	now=++tot;
    	t[now]=t[ff];t[now].v+=w;t[now].s+=S[pos]*w;
    	if(l==r)return;
    	int mid=(l+r)>>1;
    	if(pos<=mid)Modify(t[now].ls,t[ff].ls,l,mid,pos,w);
    	else Modify(t[now].rs,t[ff].rs,mid+1,r,pos,w);
    }
    ll Query(int now,int l,int r,int k)
    {
    	if(t[now].v<=k)return t[now].s;
    	if(l==r)return t[now].s/(1ll*t[now].v)*1ll*k;
    	int mid=(l+r)>>1;
    	if(k<=t[t[now].ls].v)return Query(t[now].ls,l,mid,k);
    	else return t[t[now].ls].s+Query(t[now].rs,mid+1,r,k-t[t[now].ls].v);
    }
    int main()
    {
    	m=read();n=read();
    	for(int i=1;i<=m;++i)
    	{
    		cnt++;
    		e[cnt].t=read();e[cnt+1].t=read()+1;
    		S[++sum]=e[cnt].p=e[cnt+1].p=read();
    		e[cnt].w=1;e[cnt+1].w=-1;
    		cnt++;
    	}
    	sort(&S[1],&S[sum+1]);
    	sum=unique(&S[1],&S[sum+1])-S-1;
    	sort(&e[1],&e[cnt+1]);
    	Build(rt[0],1,sum);
    	for(int i=1;i<=cnt;++i)
    	{
    		int pp=lower_bound(&S[1],&S[sum+1],e[i].p)-S;
    		Modify(rt[e[i].t],rt[e[i-1].t],1,sum,pp,e[i].w);
    	}
    	for(int i=1;i<=n;++i)
    		if(!rt[i])rt[i]=rt[i-1];
    	ll ls=1;
    	while(n--)
    	{
    		int X=read(),A=read(),B=read(),C=read();
    		int K=1+(1ll*A*ls%C+B)%C;
    		printf("%lld
    ",ls=Query(rt[X],1,sum,K));
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Unity Shader 之 渲染流水线
    C# 如何快速取到enum中的枚举数量
    Unity NGUI ScrollView 苹果式滑动
    多元线性回归~ML
    梯度下降~ML
    代价函数~ML
    ML~线性代数~python
    unity 大游戏使用什么框架
    C# Activator.CreateInstance()方法使用
    VSync Count 垂直同步
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8126343.html
Copyright © 2020-2023  润新知