题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=3932

题解

将每个进程拆成两个操作:开始进程和结束进程,离散化优先级,然后按时间排序。

建一棵主席树,区间为离散化的优先级大小,每一个时间建一个根。

对于每一个操作,令时间为i,优先级为p,如果当前时间i没有过操作,那么就在rooti1的基础上修改,否则在rooti的基础上修改。如果操作为开始,那么就在优先级为p的位置+1,否则在优先级为p的位置-1。

查询就在这个询问所对应的时间查询,因为上面的操作相当于对主席树求了一边前缀和。

如果不明白具体操作就看一看代码吧~

代码

#include <cstdio>
#include <algorithm>

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

const int maxn=100000;
const int maxk=4000000;

struct node
{
  node *son[2];
  int sum;
  long long val;
};

node *root[maxn+10],tnode[maxk+10];
int cnt,stand[maxn+10];

int updata(node *x)
{
  x->sum=x->son[0]->sum+x->son[1]->sum;
  x->val=x->son[0]->val+x->son[1]->val;
  return 0;
}

node* build(int l,int r)
{
  node *x=&tnode[++cnt];
  if(l==r)
    {
      x->sum=x->val=0;
      return x;
    }
  int mid=(l+r)>>1;
  x->son[0]=build(l,mid);
  x->son[1]=build(mid+1,r);
  updata(x);
  return x;
}

node* modify(node *now,int l,int r,int pos,int v)
{
  node *x=&tnode[++cnt];
  if(l==r)
    {
      x->sum=now->sum+v;
      x->val=now->val+v*stand[l];
      return x;
    }
  int mid=(l+r)>>1;
  if(pos<=mid)
    {
      x->son[0]=modify(now->son[0],l,mid,pos,v);
      x->son[1]=now->son[1];
    }
  else
    {
      x->son[0]=now->son[0];
      x->son[1]=modify(now->son[1],mid+1,r,pos,v);
    }
  updata(x);
  return x;
}

long long getsum(node *now,int l,int r,int k)
{
  if(k>=now->sum)
    {
      return now->val;
    }
  if(l==r)
    {
      return now->val/now->sum*k;
    }
  int mid=(l+r)>>1;
  if(k<=now->son[0]->sum)
    {
      return getsum(now->son[0],l,mid,k);
    }
  else
    {
      return now->son[0]->val+getsum(now->son[1],mid+1,r,k-now->son[0]->sum);
    }
}

struct data
{
  int t,p,v;

  data(int _t=0,int _p=0,int _v=0):t(_t),p(_p),v(_v){}

  bool operator <(const data &other) const
  {
    return t<other.t;
  }
};

bool cmp(data a,data b)
{
  return a.p<b.p;
}

data d[maxn*2+10];
int n,m,tot;
long long last;

int main()
{
  n=read();
  m=read();
  for(int i=1; i<=n; ++i)
    {
      int l=read(),r=read(),p=read();
      d[i*2-1]=data(l,p,1);
      d[i*2]=data(r+1,p,-1);
    }
  std::sort(d+1,d+n*2+1,cmp);
  last=-1;
  for(int i=1; i<=n*2; ++i)
    {
      if(d[i].p!=last)
        {
          last=d[i].p;
          d[i].p=++tot;
          stand[tot]=last;
        }
      else
        {
          d[i].p=tot;
        }
    }
  std::sort(d+1,d+n*2+1);
  root[0]=build(1,tot);
  last=1;
  for(int i=1; i<=m; ++i)
    {
      root[i]=root[i-1];
      while((last<=n*2)&&(d[last].t<=i))
        {
          root[i]=modify(root[i],1,tot,d[last].p,d[last].v);
          ++last;
        }
    }
  last=1;
  for(int i=1; i<=m; ++i)
    {
      int x=read(),a=read(),b=read(),c=read(),k=(1ll*a*(last%c)+b)%c+1;
      printf("%lld\n",last=getsum(root[x],1,tot,k));
    }
  return 0;
}