CCF认证考试 202012-5星际旅行 (100分)(线段树)

题目描述

传送门:
星际旅行

思路

根据题目描述,这道题显然是一道线段树的模板题。动力加和动力增强用对应线段树的区间加和区间乘操作。关键是旋转操作,回忆一下,线段树的区间加和区间乘都有对应的懒标记,而且加法和乘法操作的懒标记积累具有一定的交换规则。对于旋转操作,也可以定义一个旋转标记,注意到,区间旋转3次等价于没有旋转,问题是交换规则。由于乘法是对x,y,z三个坐标同步进行增幅,所以旋转和乘法操作是任意可交换的,对于加法,它对于旋转不具有交换性,但懒标记的更新过程可以旋转,定义任意一次加法(x,y,z)+(a,b,c),它对加法懒标记的更新操作为(a,b,c)向右旋转(旋转懒标记)lazyro[p]次,后进行更新即可。这样所有的加法和旋转,都等价于先加后旋转,按此规则Pushdown即可。

AC代码

#include<iostream>
#include<vector>
#include<string.h>
#include<map>
#include<algorithm>
#include<math.h>
#include <assert.h>
#include<queue>
#include<set>
#define INF 1000000000
#define p(x) x%3
#define MOD 1000000007
using namespace std;
#define maxn 10000000
using LL=long long int;
LL lazyx[maxn],lazyy[maxn],lazyz[maxn],lazymul[maxn],
lazyro[maxn],sum_x[maxn],sum_y[maxn],sum_z[maxn],lson[maxn],rson[maxn];
LL cnt=0;
inline void swap(LL& a,LL& b)
{
    LL t=a;
    a=b;
    b=t;
}
inline void pushdown(LL p,LL l,LL r)
{
    if(l==r)
    {
        lazyx[p] = lazyy[p] = lazyz[p] = lazymul[p] = lazyro[p] = 0;
        return;
    }
    LL& lchild = lson[p];
    LL& rchild = rson[p];
    if(!lchild)lchild=++cnt;
    if(!rchild)rchild=++cnt;
    LL mid = (l+r)>>1;
    if(!lazymul[p])lazymul[p] = 1;
    sum_x[lchild] =(sum_x[lchild]*(lazymul[p]%MOD)%MOD+((mid-l+1)%MOD)*(lazyx[p]%MOD)%MOD)%MOD,
    sum_x[rchild] =(sum_x[rchild]*(lazymul[p]%MOD)%MOD+((r-mid)%MOD)*(lazyx[p]%MOD)%MOD)%MOD;
    sum_y[lchild] =(sum_y[lchild]*(lazymul[p]%MOD)%MOD+((mid-l+1)%MOD)*(lazyy[p]%MOD)%MOD)%MOD,
    sum_y[rchild] =(sum_y[rchild]*(lazymul[p]%MOD)%MOD+((r-mid)%MOD)*(lazyy[p]%MOD)%MOD)%MOD;
    sum_z[lchild] =(sum_z[lchild]*(lazymul[p]%MOD)%MOD+((mid-l+1)%MOD)*(lazyz[p]%MOD)%MOD)%MOD,
    sum_z[rchild] =(sum_z[rchild]*(lazymul[p]%MOD)%MOD+((r-mid)%MOD)*(lazyz[p]%MOD)%MOD)%MOD;

    for(LL i=0;i<lazyro[p];++i)
    {
        swap(sum_x[lchild],sum_y[lchild]);
        swap(sum_y[lchild],sum_z[lchild]);
        swap(sum_x[rchild],sum_y[rchild]);
        swap(sum_y[rchild],sum_z[rchild]);
    }

    int u,v,w;

    u=lazyx[p],v=lazyy[p],w=lazyz[p];
    for(int i=0;i<lazyro[lchild];++i)
    {
        swap(v,w);
        swap(u,v);
    }

    lazyx[lchild] =(lazyx[lchild]*(lazymul[p]%MOD)%MOD+u%MOD)%MOD,
    lazyy[lchild] =(lazyy[lchild]*(lazymul[p]%MOD)%MOD+v%MOD)%MOD,
    lazyz[lchild] =(lazyz[lchild]*(lazymul[p]%MOD)%MOD+w%MOD)%MOD;

    u=lazyx[p],v=lazyy[p],w=lazyz[p];
    for(int i=0;i<lazyro[rchild];++i)
    {
        swap(v,w);
        swap(u,v);
    }
    lazyx[rchild] =(lazyx[rchild]*(lazymul[p]%MOD)%MOD+u%MOD)%MOD,
    lazyy[rchild] =(lazyy[rchild]*(lazymul[p]%MOD)%MOD+v%MOD)%MOD,
    lazyz[rchild] =(lazyz[rchild]*(lazymul[p]%MOD)%MOD+w%MOD)%MOD;


    if(lazymul[p]!=1)
    {
        if(!lazymul[lchild])
            lazymul[lchild]=1;
        lazymul[lchild] = lazymul[lchild]*(lazymul[p]%MOD)%MOD;
        if(!lazymul[rchild])
            lazymul[rchild]=1;
        lazymul[rchild] = lazymul[rchild]*(lazymul[p]%MOD)%MOD;
    }

    lazyro[lchild] = (lazyro[lchild] + lazyro[p])%3;
    lazyro[rchild] = (lazyro[rchild] + lazyro[p])%3;
    lazyx[p]=0;
    lazyy[p]=0;
    lazyz[p]=0;
    lazymul[p]=0;
    lazyro[p]=0;
}
void add(LL& p,LL l,LL r,LL L,LL R,LL a,LL b,LL c)
{
    if(!p)
    {
        p=++cnt;
    }
    if(r<L || l>R)
        return;

    if(l>=L && r<=R)
    {
        sum_x[p] =(sum_x[p]+(r-l+1)%MOD*(a%MOD)%MOD)%MOD,
        sum_y[p] =(sum_y[p]+(r-l+1)%MOD*(b%MOD)%MOD)%MOD,
        sum_z[p] =(sum_z[p]+(r-l+1)%MOD*(c%MOD)%MOD)%MOD;
        for(int i=0;i<lazyro[p];++i)
        {
            swap(b,c);
            swap(a,b);
        }
        lazyx[p] =(lazyx[p]+a%MOD)%MOD;
        lazyy[p] =(lazyy[p]+b%MOD)%MOD;
        lazyz[p] =(lazyz[p]+c%MOD)%MOD;
        return;
    }
    if(lazyx[p]||lazyy[p]||lazyz[p]||lazymul[p]||lazyro[p])
        pushdown(p,l,r);
    LL mid = (l+r)>>1;
    if(mid>=L)
        add(lson[p],l,mid,L,R,a,b,c);
    if(mid<R) 
        add(rson[p],mid+1,r,L,R,a,b,c);
    sum_x[p]=(sum_x[lson[p]]%MOD+sum_x[rson[p]]%MOD)%MOD;
    sum_y[p]=(sum_y[lson[p]]%MOD+sum_y[rson[p]]%MOD)%MOD;
    sum_z[p]=(sum_z[lson[p]]%MOD+sum_z[rson[p]]%MOD)%MOD;
}

void mul(LL& p,LL l,LL r,LL L,LL R,LL k)
{
    if(!p)
    {
        p=++cnt;
    }
    if(r<L || l>R)
        return;
    if(l>=L && r<=R)
    {
        if(!lazymul[p])
            lazymul[p]=1;
        lazymul[p] = lazymul[p]*(k%MOD)%MOD;
        lazyx[p] = lazyx[p]*(k%MOD)%MOD,
        lazyy[p] = lazyy[p]*(k%MOD)%MOD,
        lazyz[p] = lazyz[p]*(k%MOD)%MOD;
        sum_x[p] = sum_x[p]*(k%MOD)%MOD,
        sum_y[p] = sum_y[p]*(k%MOD)%MOD,
        sum_z[p] = sum_z[p]*(k%MOD)%MOD;
        return;
    }
    if(lazyx[p]||lazyy[p]||lazyz[p]||lazymul[p]||lazyro[p])
        pushdown(p,l,r);
    LL mid = (l+r)>>1;
    if(mid>=L)
        mul(lson[p],l,mid,L,R,k);
    if(mid<R) 
        mul(rson[p],mid+1,r,L,R,k);
    sum_x[p]=(sum_x[lson[p]]%MOD+sum_x[rson[p]]%MOD)%MOD;
    sum_y[p]=(sum_y[lson[p]]%MOD+sum_y[rson[p]]%MOD)%MOD;
    sum_z[p]=(sum_z[lson[p]]%MOD+sum_z[rson[p]]%MOD)%MOD;
}

void rotate(LL& p,LL l,LL r,LL L,LL R)
{
    if(!p)
    {
        p=++cnt;
    }
    if(r<L || l>R)
    return;
    if(l>=L && r<=R)
    {
        lazyro[p]++;
        lazyro[p]%=3;
        swap(sum_x[p],sum_y[p]);
        swap(sum_y[p],sum_z[p]);
        return;
    }
    if(lazyx[p]||lazyy[p]||lazyz[p]||lazymul[p]||lazyro[p])
        pushdown(p,l,r);
    LL mid = (l+r)>>1;
    if(mid>=L)
        rotate(lson[p],l,mid,L,R);
    if(mid<R)
        rotate(rson[p],mid+1,r,L,R);
    sum_x[p]=(sum_x[lson[p]]%MOD+sum_x[rson[p]]%MOD)%MOD;
    sum_y[p]=(sum_y[lson[p]]%MOD+sum_y[rson[p]]%MOD)%MOD;
    sum_z[p]=(sum_z[lson[p]]%MOD+sum_z[rson[p]]%MOD)%MOD;
}

void query(LL& p,LL l,LL r,LL L,LL R,LL& a,LL& b,LL& c)
{
    if(!p)
    {
        p=++cnt;
    }
    if(r<L || l>R)
        return;
    if(l>=L && r<=R)
    {
        a = (a+sum_x[p]%MOD)%MOD,
        b = (b+sum_y[p]%MOD)%MOD,
        c = (c+sum_z[p]%MOD)%MOD;
        return;
    }
    if(lazyx[p]||lazyy[p]||lazyz[p]||lazymul[p]||lazyro[p])
        pushdown(p,l,r);
    LL mid = (l+r)>>1;
    if(mid>=L)
        query(lson[p],l,mid,L,R,a,b,c);
    if(mid<R)
        query(rson[p],mid+1,r,L,R,a,b,c);
}

int main()
{
    LL n,m;cin>>n>>m;
    LL l=1,r=n;
    LL root=++cnt;
    for(LL i=0;i<m;++i)
    {
        LL option;cin>>option;
        LL L,R;cin>>L>>R;
        switch (option)
        {
        case 1:
            LL a,b,c;cin>>a>>b>>c;
            add(root,l,r,L,R,a,b,c);
            break;
        case 2:
            LL k;cin>>k;
            mul(root,l,r,L,R,k);
            break;
        case 3:
            rotate(root,l,r,L,R);
            break;
        case 4:
            LL f=0,d=0,e=0;
            query(root,l,r,L,R,f,d,e);
            cout<<((f%MOD)*(f%MOD)%MOD+(d%MOD)*(d%MOD)%MOD+(e%MOD)*(e%MOD)%MOD)%MOD<<endl;
            break;
        }
    }
    return 0;
}
  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
根据引用内容,代码片段展示了一个自定义的ID主键生成器的配置类。在该配置类中,使用了Hutool工具类中的RandomUtil来生成1-31之间的随机数作为workerId和dataCenterId的值。这个生成器的目的是为了防止在多线程批量插入数据时出现ID主键重复的情况。 引用内容是一个GitHub的Issue链接,其中讨论了MyBatis-plus在批量插入数据时可能出现的主键冲突问题。根据你提供的信息,问题描述为"Duplicate entry '2322-3c9038d5-683b-4ccf-9d23-e36fb8b100ab' for key 'PRIMARY'"。这个错误通常是由于在插入数据时,主键出现了重复值导致的。 根据引用内容中的代码片段,自定义的ID主键生成器使用了随机数生成workerId和dataCenterId。这意味着在多线程批量插入数据时,由于随机数生成的workerId和dataCenterId可能重复,导致了主键冲突的错误。为了解决这个问题,你可以检查代码中workerId和dataCenterId的生成方式,并确保生成的值不会重复。 另外,根据引用内容,你提到部署环境采用了一台服务器Docker多节点,多线程批量插入数据。在这种情况下,主键冲突的错误可能是由于多个线程同时插入数据导致的。你可以考虑使用布式ID生成器或者其他解决方案来确保在多节点、多线程环境下生成唯一的主键值,从而避免主键冲突的问题。 综上所述,要解决"Duplicate entry '2322-3c9038d5-683b-4ccf-9d23-e36fb8b100ab' for key 'PRIMARY'"的问题,你可以检查自定义ID主键生成器的代码,确保生成的workerId和dataCenterId不会重复,并考虑在多节点、多线程环境下使用布式ID生成器或其他解决方案来生成唯一的主键值。123 #### 引用[.reference_title] - *1* *2* *3* [【问题集锦 -02】MyBatis-Plus多节点多线程批量插入(insertBatch) 唯一主键ID冲突...for key ‘PRIMARY‘)](https://blog.csdn.net/weixin_42257984/article/details/125084583)[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^chatsearchT3_1"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值