BZOJ 3932(CQOI 2015) 题解

题目大意

实现一个查询系统。
每个任务用三元组(Si,Ei,Pi)描述表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行),其优先级为Pi。调度系统会经常向查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个)的优先级之和是多少。

我的做法

把p离散化。
按照离散化后的p建立可持久化线段树。
把一个任务拆成两个扔进线段树中。
查询时注意多个任务优先级相同的情况。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
struct tree
{
    int l,r;
    tree *ls,*rs;
    int num;
    ll sum;
    tree()
    {
        l=r=num=0;
        sum=0;
        ls=rs=0;
    }
};
tree *root[100010];
void mt(tree *&p)
{
    if(p->l==p->r)
     return;
    p->num=p->ls->num+p->rs->num;
    p->sum=p->ls->sum+p->rs->sum;
}
void build(tree *&p,int l,int r)
{
    p=new tree;
    p->l=l;
    p->r=r;
    if(l==r)
     return;
    int mid=(l+r)>>1;
    build(p->ls,l,mid);
    build(p->rs,mid+1,r);
}
void insert(tree *&p1,tree *&p2,int x,int v1,ll v2)
{
    p2=new tree(*p1);
    if(p2->l==p2->r)
    {
        p2->num+=v1;
        p2->sum+=v2;
        return;
    }
    int mid=(p2->l+p2->r)>>1;
    if(x<=mid)
     insert(p1->ls,p2->ls,x,v1,v2);
    else
     insert(p1->rs,p2->rs,x,v1,v2);
    mt(p2);
}
ll query(tree *&p,int k)
{
    if(k==0)
     return 0;
    if(p->l==p->r)
     return p->sum/p->num*k;
    if(k>=p->num)
     return p->sum;
    int mid=(p->l+p->r)>>1;
    int s=p->ls->num;
    if(k<=s)
     return query(p->ls,k);
    return p->ls->sum+query(p->rs,k-s);
}
struct p
{
    int a,b,c;
    ll d;
    p(int a_=0,int b_=0,int c_=0,ll d_=0)
    {
        a=a_;
        b=b_;
        c=c_;
        d=d_;
    }
};
bool cmp(p a,p b)
{
    return a.a<b.a;
}
p a[200010];
int d[100010];
int x[100010];
int y[100010];
int z[100010];
int main()
{
    freopen("bzoj3932.in","r",stdin);
    freopen("bzoj3932.out","w",stdout);
    int n,m;
    scanf("%d%d",&m,&n);
    int i;
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x[i],&y[i],&z[i]);
        d[i]=z[i];
    }
    sort(d+1,d+m+1);
    int tot=unique(d+1,d+m+1)-d-1;
    for(i=1;i<=m;i++)
    {
        int t=lower_bound(d+1,d+tot+1,z[i])-d;
        a[2*i-1]=p(x[i],t,1,z[i]);
        a[2*i]=p(y[i]+1,t,-1,-z[i]);
    }
    build(root[0],1,tot);
    sort(a+1,a+2*m+1,cmp);
    for(i=1;i<=2*m;i++)
    {
        if(a[i].a>n)
         break;
        tree *now;
        insert(root[a[i-1].a],now,a[i].b,a[i].c,a[i].d);
        root[a[i].a]=now;
    }
    for(i=1;i<=n;i++)
     if(!root[i])
      root[i]=root[i-1];
    ll pre=1;
    for(i=1;i<=n;i++)
    {
        int X,A,B,C,K;
//      scanf("%d%d%d%d",&X,&A,&B,&C);
//      K=1+(A*pre+B)%C;
        scanf("%d%d",&X,&K);
        pre=query(root[X],K);
        printf("%lld\n",pre);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用所述,交错序列是一个仅由0和1构成的序列,其中没有相邻的1(可以有相邻的0)。特征值定义为x^ay^b,其中x和y分别表示0和1出现的次数。长度为n的交错序列可能有多个。问题要求计算所有长度为n的交错序列特征值的和除以m的余数。 根据引用所述,输入文件包含一个行,该行包含三个整数n、a、b和m。其中,1≤n≤10000000,0≤a、b≤45,m<100000000。 为了解决这个问题,可以使用动态规划和矩阵快速幂优化的方法,具体实现可以参考引用提到的相关算法。算法的思路是通过计算长度为n的交错序列的特征值,然后将所有特征值求和并对m取余数。 具体步骤如下: 1. 使用动态规划计算长度为n的所有交错序列的特征值,将结果保存在一个矩阵中。 2. 使用矩阵快速幂优化,将动态规划的过程进行优化。 3. 对优化后的结果进行求和,并对m取余数。 4. 输出结果。 参考引用给出的博客中的代码实现,可以帮助你更好地理解和实现该算法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [BZOJ5298 CQOI2018 交错序列 【DP+矩阵快速幂优化】*](https://blog.csdn.net/weixin_30892987/article/details/99470493)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值