bzoj 3932(主席树)

3932: [CQOI2015]任务查询系统

Time Limit: 20 Sec   Memory Limit: 512 MB
Submit: 1452   Solved: 529
[ Submit][ Status][ Discuss]

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


解题思路:模板题,但是wa了无数次


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define ll long long 
using namespace std;
int n,m,len,gen,cnt,tail,tail1;
ll sum[18700000],ans,Pre;
int l[18700000],r[18700000],val[18700000],root[110000];
int s[110000],e[110000],p[110000];
int to[210000],next[210000],h[210000];
int go[210000],con[210000],hg[210000],poo[110000];
int x[210000],y[210000];
struct ss
 {
    int zhi,dui;
 }q[110000];
 
inline ll read()
{
    char y; ll x=0,f=1; y=getchar();
    while (y<'0' || y>'9') {if (y=='-') f=-1; y=getchar();}
    while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
    return x*f;
}
 
void insert(int x,int y)
 {
    ++len; to[len]=y; next[len]=h[x]; h[x]=len;
 }
  
void insert1(int x,int y)
 {
    ++gen; go[gen]=y; con[gen]=hg[x]; hg[x]=gen; 
 }
 
 
void build(int rot,int &now,int dui,int lo,int ro,int xl,int xr,int yl,int yr)
 {
    if (now==0) now=++cnt,sum[now]=sum[dui],val[now]=val[dui];
    for (int i=xl;i<=xr;++i) ++val[now],sum[now]+=poo[x[i]];
    for (int i=yl;i<=yr;++i) --val[now],sum[now]-=poo[y[i]];
    if (lo==ro) return;
    int mid=(lo+ro)/2;
    if (x[xl]>mid && y[yl]>mid || x[xr]<=mid && y[yr]<=mid)
{
  if (x[xl]>mid && y[yl]>mid)
   {
     l[now]=l[dui]; 
     build(rot,r[now],r[dui],mid+1,ro,xl,xr,yl,yr);
}else
{
r[now]=r[dui];
build(rot,l[now],l[dui],lo,mid,xl,xr,yl,yr);
}
}else
{
   int u1=xl; int u2=yl;
while (x[u1]<=mid && u1<=xr)++u1; --u1;
while (y[u2]<=mid && u2<=yr)++u2; --u2;
build(rot,l[now],l[dui],lo,mid,xl,u1,yl,u2);
   ++u1; ++u2;
build(rot,r[now],r[dui],mid+1,ro,u1,xr,u2,yr);
}
 }
 
void query(int now,int size,int lo,int ro)
 {
    int mid=(lo+ro)/2;
    if (lo==ro)
     {
        ans+=(long long) (size)*poo[lo];
        return;
      }
    if (size==0) return;
    if (val[l[now]]<=size) 
     {
        ans+=sum[l[now]];
        query(r[now],size-val[l[now]],mid+1,ro);
      }else
       {
        query(l[now],size,lo,mid);
       }
 }
 
bool cmp(ss x,ss y)
 {
    return x.zhi<y.zhi;
 }
 
int main()
{
freopen("main.in","r",stdin);
freopen("main.out","w",stdout);
    cnt=0;
    m=read(); n=read(); 
    for (int i=1;i<=m;++i)
     {
        s[i]=read(); e[i]=read(); p[i]=read();
        q[i].zhi=p[i]; q[i].dui=i; 
     }
    sort(q+1,q+m+1,cmp);
    int sug=0; 
    for (int i=1;i<=m;++i)
     {
        if (q[i].zhi!=q[i-1].zhi) ++sug; 
        poo[sug]=p[q[i].dui]; p[q[i].dui]=sug;
     }
    for (int i=1;i<=m;++i)
    {
        insert(s[i],p[i]); insert1(e[i]+1,p[i]);
    }
    for (int i=1;i<=n;++i)
     {
       int u=h[i]; tail=0; tail1=0;
       while (u!=0)
        {
          ++tail; x[tail]=to[u];
          u=next[u];
        }
       u=hg[i];
       while (u!=0)
        {
          ++tail1; y[tail1]=go[u]; 
          u=con[u]; 
        }
       sort(x+1,x+tail+1); sort(y+1,y+tail1+1);
       build(i,root[i],root[i-1],1,n,1,tail,1,tail1);
     }
    Pre=1;
    for (int i=1;i<=n;++i)
     {
        int xi,ai,bi,ci;
        xi=read(); ai=read(); bi=read(); ci=read();
        long long kg=1+(ai*Pre+bi)%ci;
        if (val[root[xi]]<kg) 
         {
            printf("%lld\n",sum[root[xi]]);
            Pre=sum[root[xi]];
          }else
            {
              ans=0;
              query(root[xi],kg,1,m);
              printf("%lld\n",ans);
              Pre=ans;  
            }
     }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值