1 条题解

  • 0
    @ 2025-8-24 22:07:11

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar zifanwang
    RP++

    搬运于2025-08-24 22:07:11,当前版本为作者最后更新于2023-08-11 12:53:43,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    提高 T1 难度 远古 JOI 题。这东西能评黑???

    干什么

    有两个长度为 nn 个序列 (x1,x2,,xn),(y1,y2,,yn)(x_1,x_2,\dots,x_n),(y_1,y_2,\dots,y_n),初始化 xi=yi=ix_i=y_i=i。有 qq 次操作,每次给你三个数 X,D,LX,D,L,若 D=1D=1 将所有满足 xiXx_i\le Xiiyiy_i2L2L,若 D=2D=2 则将所有满足 yi>Xy_i> Xiixix_i2L2L,求出最终的 x,yx,y 序列。

    怎么做

    发现 x,yx,y 两个序列任意时刻都是单调递增的,两种操作分别是前缀减和后缀加,二分出修改的区间然后树状数组维护即可,时间复杂度 O(qlog2n)O(q\log^2 n)

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define mxn 200003
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define rept(i,a,b) for(int i=a;i<b;++i)
    #define drep(i,a,b) for(int i=a;i>=b;--i)
    using namespace std;
    struct node{
    	ll x,d,l;
    }a[mxn];
    int n,q;
    struct tree{
    	ll c[mxn];
    	void add(int x,int y){for(;x<=n;x+=x&-x)c[x]+=y;}
    	ll ask(int x){
    		ll s=0;
    		for(;x;x-=x&-x)s+=c[x];
    		return s;
    	}
    }c1,c2;
    signed main(){
    	scanf("%d%d",&n,&q);
    	rep(i,1,q)scanf("%lld%lld%lld",&a[i].x,&a[i].d,&a[i].l),a[i].l<<=1;
    	rep(i,1,n)c1.add(i,1),c2.add(i,1);
    	drep(j,q,1){
    		if(a[j].d==1){
    			int l=1,r=n;
    			while(l<r){
    				int mid=(l+r+1)>>1;
    				if(c1.ask(mid)<=a[j].x)l=mid;
    				else r=mid-1;
    			}
    			if(c1.ask(l)<=a[j].x)c2.add(1,-a[j].l),c2.add(l+1,a[j].l);
    		}else{
    			int l=1,r=n;
    			while(l<r){
    				int mid=(l+r)>>1;
    				if(c2.ask(mid)>a[j].x)r=mid;
    				else l=mid+1;
    			}
    			if(c2.ask(l)>a[j].x)c1.add(l,a[j].l);
    		}
    	}
    	rep(i,1,n)printf("%lld\n",(c1.ask(i)-c2.ask(i))>>1);
    	return 0;
    }
    
    • 1

    信息

    ID
    4118
    时间
    1000ms
    内存
    125MiB
    难度
    7
    标签
    递交数
    0
    已通过
    0
    上传者