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

    [CQOI2015]任务查询系统

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:

    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

    输出样例#1:

    2
    8
    11

    说明

    样例解释

    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的一个排列

    Solution

    静态主席树...

    简述题意,区间修改,单点查询,差分hhhh...

    我们以时间轴作为下标,优先级作为权值建主席树

    然后query的时候如果已经确定到节点了,就只去k的节点的值

        if(l==r) return t[u].sum/(1ll*t[u].cnt)*1ll*k;
        //一个节点存多个相同的权值,有cnt个,我们只要算k个就够了
    

    然后如果当前节点的左子树的节点个数>k,我们就要在查询有子树的基础上还要加上左子树的权值和

    if(k<=num) return query(t[u].l,l,mid,k);
    else return query(t[u].r,mid+1,r,k-num)+t[t[u].l].sum;
    

    Code

    #include<bits/stdc++.h>
    #define lol long long
    #define Min(a,b) ((a)<(b)?(a):(b))
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define rg register
    #define mid ((l+r)>>1)
    #define in(i) (i=read())
    using namespace std;
    
    const int N=1e5+10;
    
    int read() {
        int ans=0,f=1; char i=getchar();
        while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
        while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+i-'0',i=getchar();
        return ans*=f;
    }
    
    int n,m,num,tot;
    int a[N],b[N],rt[N<<6];
    lol pre=1;
    
    struct Tree {
        lol sum; int cnt,l,r;
    }t[N<<6];
    vector<int>v[N],g[N];
    
    void update(int &u,int l,int r,int pre,int pos,int v) {
        u=++tot; t[u]=t[pre];
        t[u].cnt+=v, t[u].sum+=1ll*v*b[pos];
        if(l==r) return;
        if(pos<=mid) update(t[u].l,l,mid,t[pre].l,pos,v);
        else update(t[u].r,mid+1,r,t[pre].r,pos,v);
    }
    
    lol query(int u,int l,int r,int k) {
        int num=t[t[u].l].cnt;
        if(l==r) return t[u].sum/(1ll*t[u].cnt)*1ll*k;
        if(k<=num) return query(t[u].l,l,mid,k);
        else return query(t[u].r,mid+1,r,k-num)+t[t[u].l].sum;
    }
    
    int main()
    {
        in(m), in(n);
        for (rg int i=1,x,y;i<=m;i++) {
            in(x), in(y), in(a[i]), b[i]=a[i], y++;
            v[x].push_back(i), g[y].push_back(i);//v[]存左端点,g[]存右端点
        }
        sort(b+1,b+1+m); int num=unique(b+1,b+1+m)-b-1;
        for (rg int i=1;i<=n;i++) {
            rt[i]=rt[i-1];
            for (rg unsigned int j=0;j<v[i].size();j++) {
                int p=lower_bound(b+1,b+1+num,a[v[i][j]])-b;
                update(rt[i],1,num,rt[i],p,1);//pre=rt[i],因为是同一个时间
            }
            for (rg unsigned int j=0;j<g[i].size();j++) {
                int p=lower_bound(b+1,b+1+num,a[g[i][j]])-b;
                update(rt[i],1,num,rt[i],p,-1);//同上
            }
        }
        for (rg int i=1,x,a,b,c,k;i<=n;i++) {
            in(x), in(a), in(b), in(c);
            k=(1ll*a*pre+b)%c+1;
            if(k>t[rt[x]].cnt) pre=t[rt[x]].sum;
            else pre=query(rt[x],1,num,k);
            printf("%lld
    ",pre);
        }
    }
    
  • 相关阅读:
    POJ 3140 Contestants Division (树dp)
    POJ 3107 Godfather (树重心)
    POJ 1655 Balancing Act (树的重心)
    HDU 3534 Tree (经典树形dp)
    HDU 1561 The more, The Better (树形dp)
    HDU 1011 Starship Troopers (树dp)
    Light oj 1085
    Light oj 1013
    Light oj 1134
    FZU 2224 An exciting GCD problem(GCD种类预处理+树状数组维护)同hdu5869
  • 原文地址:https://www.cnblogs.com/real-l/p/9885717.html
Copyright © 2011-2022 走看看