洛谷P4433 [COCI2009-2010#1] ALADIN

题目描述

给你 𝑛n 个盒子,有 𝑞q 个操作,操作有两种:

  • 第一种操作输入格式为 1 L R A B,表示将编号为 𝐿L 到 𝑅R 的盒子里的石头数量变为 (𝑋−𝐿+1)×𝐴 mod 𝐵(X−L+1)×AmodB,其中 𝑋X 为盒子的编号。
  • 第二种操作输入格式为 2 L R,表示查询编号为 𝐿L 到 𝑅R 的盒子里的石头总数。

输入格式

第一行有两个数字 𝑛n(1≤𝑛≤1091≤n≤109),𝑞q (1≤𝑞≤5×1041≤q≤5×104)。

接下来 𝑞q 行表示询问操作。

输出格式

对于每个第二种操作,输出石头总数。

输入输出样例

输入 #1

6 3
2 1 6
1 1 5 1 2
2 1 6

输出 #1

0
3

输入 #2

4 5
1 1 4 3 4
2 1 1
2 2 2
2 3 3
2 4 4

输出 #2

3
2
1
0

输入 #3

4 4
1 1 4 7 9
2 1 4
1 1 4 1 1
2 1 4

输出 #3

16
0

说明/提示

  • 对于 30%30% 的数据,𝑛,𝑞≤103n,q≤103;
  • 对于 70%70% 的数据,𝑞≤103q≤103。
  • Code:

    /*Code by 520 -- 9.7*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);++(i))
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);--(i))
    #define lson l,m,rt<<1
    #define rson m,r,rt<<1|1
    using namespace std;
    const int N=1000005;
    int n,m,flag[N],L[N],R[N],*Q[N],cnt,tot,val[N];
    ll A[N],B[N];
    struct node{
        ll sum,a,b,st,len;
    }t[N];
    int gi(){
        int a=0;char x=getchar();
        while(x<'0'||x>'9')x=getchar();
        while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return a;
    }
    il bool cmp(int *a,int *b){return *a<*b;}
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll calc(ll a,ll b,ll n){
        ll x=a/b;a%=b;
        ll sum=n*(n+1)/2*x;
        if(!a||!b) return sum;
        ll lala=n/b,m=a*n/b;
        return sum+n*m-calc(b,a,m)+lala;
    }
    il ll solve(ll a,ll b,ll n){
        if(n<1)return 0;
        ll g=gcd(a,b);
        return n*(n+1)/2*a-b*calc(a/g,b/g,n);
    }
    il void pushup(int rt){t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum;}
    il void gai(ll A,ll B,ll st,int rt){
        t[rt].a=A,t[rt].b=B,t[rt].st=st;
        t[rt].sum=solve(A,B,st+t[rt].len-1)-solve(A,B,st-1);
    }    
    il void pushdown(int rt){
        if(t[rt].b){
            gai(t[rt].a,t[rt].b,t[rt].st,rt<<1);
            gai(t[rt].a,t[rt].b,t[rt].st+t[rt<<1].len,rt<<1|1);
            t[rt].b=0;
        }
    }
    void build(int l,int r,int rt){
        if(l+1==r){t[rt]=node{0,0,0,0,val[r]-val[l]};return;}
        int m=l+r>>1;
        t[rt]=node{0,0,0,0,val[r]-val[l]};
        build(lson),build(rson);
    }
    void update(ll A,ll B,int L,int R,int l,int r,int rt){
        if(R<=l||r<=L)return;
        if(L<=l&&R>=r){gai(A,B,val[l]-val[L]+1,rt);return;}
        pushdown(rt);
        int m=l+r>>1;
        if(L<=m) update(A,B,L,R,lson);
        if(R>=m) update(A,B,L,R,rson);
        pushup(rt);
    }
    ll query(int L,int R,int l,int r,int rt){
        if(R<=l||r<=L)return 0;
        if(L<=l&&R>=r)return t[rt].sum;
        pushdown(rt);
        int m=l+r>>1;
        ll ret=0;
        if(L<=m) ret+=query(L,R,lson);
        if(R>=m) ret+=query(L,R,rson);
        return ret;
    }
    int main(){
        n=gi(),m=gi();
        For(i,1,m) {
            flag[i]=gi(),L[i]=gi()-1,R[i]=gi(),Q[++tot]=&L[i],Q[++tot]=&R[i];
            if(flag[i]==1) A[i]=gi(),B[i]=gi();
        }
        sort(Q+1,Q+tot+1,cmp);
        int lst=-1;
        For(i,1,tot) if(*Q[i]!=lst) lst=*Q[i],*Q[i]=++cnt,val[cnt]=lst;else *Q[i]=cnt;
        build(1,cnt,1);
        For(i,1,m)
            if(flag[i]==1) update(A[i],B[i],L[i],R[i],1,cnt,1);
            else printf("%lld\n",query(L[i],R[i],1,cnt,1));
        return 0;
    } 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值