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

    [CQOI2015]任务查询系统

    https://www.luogu.org/problem/show?pid=3168

    题目描述

    最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。超级计算机中的任务用三元组(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的一个排列

    数据结构:主席树

    联想poj 2104 K-th Number 

    poj那道题找区间第k小的数,本题是找区间前k小的数的和

    所以,先离散化优先级,以时间为下标,以优先级为区间建立主席树。

    维护每个时间的优先级总和 sum ,正在进行的任务数量 countt

    前缀和转化,开始时间+,结束时间后面1个-

    所以,对任务的开始结束按时间从小到大的顺序插入

    注意1:一定要排序

    否则,由于同一任务插入后接着删除,加减抵消,主席树中sum[x]最后剩下的是x时间的最后一项任务的优先级,而不是x时间所有任务的优先级总和

    在插入时,

    注意2:没有作为任务的开始和结束出现的时间点,要用前一个时间点给它赋值

    否则,询问时如果问到这样的时间点x,由于没有以x为根建立线段树,root[x]=0,查询结果也是0

    具体实现参照代码中标注“important”那一行

    就是枚举时间范围,不管会不会出现先都给它的root赋值为前一个的root,然后判断这一时间点是否在任务中出现过,出现过直接覆盖原来的赋值

    由于前面对任务的时间排了序,所以除去插入的时间,是O(时间范围)的

    这一项没想到,卡了一晚上

    然后就查询吧,然而这里还有一个坑~

    注意3:当到达叶子节点时,答案不能直接加上叶子节点的优先级之和

    因为有可能叶子节点的任务数>k,所以答案+叶子节点的优先机制和/叶子节点的任务数*k

    还有一个小细节:40*n的空间

    平常都是20*n,这次因为对每个任务都有2个时间点,所以再翻倍

    至于平常为什么是20*n,不知道。。。。。。。

    求助路过的大佬

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #define N 100001
    using namespace std;
    int m,n,tot,p[N],hash[N];
    int root[N*4],lch[N*40],rch[N*40],cnt,countt[N*40];
    long long sum[N*40];
    long long ans;
    struct node
    {
        int p,pos,co;
    }q[N*2];
    void discrete()
    {
        sort(p+1,p+m+1);
        tot=unique(p+1,p+m+1)-(p+1);
        for(int i=1;i<=m;i++) hash[i]=lower_bound(p+1,p+tot+1,hash[i])-p;
    }
    inline void insert(int pre,int & now,int l,int r,int w,int c)
    {
        sum[now=++cnt]=sum[pre]+(long long)c*p[w];
        countt[now]=countt[pre]+c;
        if(l==r) return;
        int mid=l+r>>1;
        if(w<=mid) 
        {
            rch[now]=rch[pre];
            insert(lch[pre],lch[now],l,mid,w,c);
        }
        else 
        {
            lch[now]=lch[pre];
            insert(rch[pre],rch[now],mid+1,r,w,c);
        }
    }
    inline void query(int y,int l,int r,long long k)
    {
        if(l==r) 
        {
            ans+=sum[y]/countt[y]*k;    return;
        }
        if(countt[y]<=k) 
        {
            ans+=sum[y];    return;
        }
        int mid=l+r>>1,tmp=countt[lch[y]];
        if(k<=tmp) query(lch[y],l,mid,k);
        else
        {
            ans+=sum[lch[y]];
            query(rch[y],mid+1,r,k-tmp);
        }
    }
    inline bool comp(node k,node l)
    {
        return k.pos<=l.pos;
    }
    int main()
    {
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&q[i*2-1].pos,&q[i*2].pos,&p[i]); 
            q[i*2].pos++;
            hash[i]=p[i];
        }
        discrete();
        for(int i=1;i<=m;i++) 
        {
            q[i*2-1].p=hash[i];
            q[i*2].p=hash[i];
            q[i*2-1].co=1;
            q[i*2].co=-1;    
        }
        sort(q+1,q+2*m+1,comp);
        int j=1;
        for(int i=1;i<=n;i++)
         {
             root[i]=root[i-1];//This is very important
             while(j<=2*m&&q[j].pos==i)
             {
                 insert(root[i],root[i],1,tot,q[j].p,q[j].co);
                 j++;
            }
         }
        long long p=1,a,b,c,k;
        int x;
        for(int i=1;i<=n;i++)
        {
            ans=0;
            scanf("%d",&x);
            scanf("%lld%lld%lld",&a,&b,&c);
            k=1ll+(a*p+b)%c;
            if(k>=countt[root[x]]) ans=sum[root[x]];
            else query(root[x],1,tot,k);
            printf("%lld
    ",ans);
            p=ans;
        }
    }

    做了一下午没做出来,晚上问了学长,原因:

    离散化了时间,即以时间为下标,又以时间为区间建立主席树

    最后写到查询的时候,要从区间内出现过的优先级中去前k小

    当时只想到暴力搜索,或优先队列

    太麻烦,不写了

    根本原因还是对主席树理解不透彻

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #define N 100001
    using namespace std;
    vector<int>t[N];
    bool v[N];
    int m,n,tot,p[N],e[2*N],hash[2*N];
    int root[N],lch[N*20],rch[N*20],cnt,countt[N*20];
    long long sum[N*20];
    long long ans;
    struct node
    {
        int p,pos,co;
    }q[N*2];
    void discrete()
    {
        sort(e+1,e+2*m+1);
        tot=unique(e+1,e+2*m+1)-(e+1);
        for(int i=1;i<=2*m;i++) hash[i]=lower_bound(e+1,e+tot+1,hash[i])-e;
    }
    inline void insert(int pre,int & now,int l,int r,int w,int pos,int jj)
    {
        sum[now=++cnt]=sum[pre]+w;
        countt[now]=countt[pre]+jj;
        if(l==r) return;
        int mid=l+r>>1;
        if(pos<=mid) 
        {
            rch[now]=rch[pre];
            insert(lch[pre],lch[now],l,mid,w,pos,jj);
        }
        else 
        {
            lch[now]=lch[pre];
            insert(rch[pre],rch[now],mid+1,r,w,pos,jj);
        }
    }
    inline void query(int y,int l,int r,int k,int opl,int opr)
    {
        if(countt[y]<=0) return;
        /*if(countt[y]<=k) 
        {
            ans+=sum[y];
            return;
        }*/
        if(opl<=l&&opr>=r)
        {
            if(k>=count[y]) ans+=sum[y];
            else 
            {
                for(int i=l;i<=r;i++)
                if(!v[i]) 
                {
                    sort(t[i].begin(),t[i].end());
                     v[i]=true;
                    ans+=k个。。。。。 
                }
                
            }
        }
        if(l==r) 
        {    
            if(k<countt[y])
            {
                if(!v[l]) 
                {
                    sort(t[l].begin(),t[l].end());
                    v[l]=true;
                }
                for(int i=1;i<=k;i++) ans+=t[l][i-1];
            }
            else ans+=sum[y];  
            return;
        }    
        int mid=l+r>>1/*,tmp=countt[lch[y]]*/;
        if(time<=/*tmp*/mid) query(lch[y],l,mid,k,time);
        else 
        {
            //ans+=sum[lch[y]];
            query(rch[y],mid+1,r,/*k-tmp*/k,time);
        }    
    }
    inline bool cmp(node k,node l)
    {
        /*if(k.pos<l.pos) return 1;
        if(k.p>l.p) return 1;
        return 0;*/
        return k.pos<=l.pos;
    }
    int main()
    {
        /*freopen("cqoi15_query1.in","r",stdin);
        freopen("cqoi15_query.out","w",stdout);*/
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&e[i*2-1],&e[i*2],&p[i]);
            t[e[i*2-1]].push_back(p[i]);
            hash[i*2-1]=e[i*2-1];hash[i*2]=e[i*2];
        }
        discrete();
        for(int i=1;i<=m;i++) 
        {
            q[i*2-1].p=p[i];
            q[i*2-1].pos=hash[i*2-1];
            q[i*2].p=-p[i];
            q[i*2].pos=hash[i*2]+1;
            q[i*2-1].co=1;
            q[i*2].co=-1;
        }
        sort(q+1,q+2*m+1,cmp);
        for(int i=1;i<=2*m;i++)
            insert(root[q[i-1].pos],root[q[i].pos],1,tot+1,q[i].p,q[i].pos,q[i].co);
        int p=1,a,b,c,x,k;
        for(int i=1;i<=n;i++)
        {
            ans=0;
            scanf("%d%d%d%d",&x,&a,&b,&c);
            k=1+(a*p+b)%c;
            x=upper_bound(e+1,e+tot+1,x)-e-1;
            query(root[x],1,m,k,1,x);
            printf("%lld
    ",ans);
            p=ans;
        }
    }
    失败代码
  • 相关阅读:
    录屏软件 OBS Studio
    ubuntu安装以及美化
    win10系统软件安装列表
    GNSS数据的弱点
    理解TomoDD生成的地壳模型的格式
    acrobat DC install
    matlab平行运算 parrelpool
    写申请地震台网数据的申请表
    强震动数据的网站
    visual studio各个版本的key
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6366165.html
Copyright © 2011-2022 走看看