E

线段树

每次从bib_ibi开始,给长度为aia_iai的子数组都加1,这是个循环数组,超过n了会回到开头。

每次加的元素aia_iai是从数组里取的,也就是需要动态修改,查询。

aia_iai很大的话,其实加操作就是一个后缀,一个前缀,加中间多段完整的,每段完整的都一样,三次区间加即可。线段树维护。

struct Tree{
    struct Node{
        int l,r;
        ll sum,add;
    }tr[N<<2];
     
    void pushup(int u){
        tr[u].sum=tr[ls].sum+tr[rs].sum;
    }
     
    void pushdown(int u){
        if(tr[u].add){
            tr[ls].sum+=tr[u].add;
            tr[rs].sum+=tr[u].add;
            tr[ls].add+=tr[u].add;
            tr[rs].add+=tr[u].add;
            tr[u].add=0;
        }
    }
     
    void build(int u,int l,int r){
        tr[u]={l,r,0,0};
        if(l==r){
            return;
        }
        int mid=(l+r)>>1;
        build(ls,l,mid);    build(rs,mid+1,r);
        pushup(u);
    }
     
    void modify(int u,int l,int r,int val){
        if(tr[u].l>=l&&tr[u].r<=r){   
            tr[u].sum+=val;
            tr[u].add+=val;
            return ;
        }
        else{
            int mid=(tr[u].l+tr[u].r)>>1;
            pushdown(u);
            if(mid>=l)   modify(ls,l,r,val);
            if(r>mid) modify(rs,l,r,val);
            pushup(u);  
        }
    }
     
    ll query(int u,int l,int r){
        if(r<tr[u].l||tr[u].r<l)  return 0;
        if(l<=tr[u].l&&tr[u].r<=r)    return  tr[u].sum;
        pushdown(u);
        return query(ls,l,r)+query(rs,l, r);
    }
}t;
void solve(void){ 
	int n,m;
	cin>>n>>m;
	t.build(1,1,n);
	rep(i,1,n){
		int x;
		cin>>x;
		t.modify(1,i,i,x);
	}
	rep(i,1,m){
		int x;
		cin>>x;
		x++;
		int b=t.query(1,x,x);
		t.modify(1,x,x,-b);
		t.modify(1,1,n,b/n);
		b-=b/n*n;
		if(b){
			int l=x+1,r=x+b;
			if(l>n)l-=n;
			if(r>n)r-=n;
			if(r>=l){
				t.modify(1,l,r,1);
			} 
			else{
				t.modify(1,l,n,1);
				t.modify(1,1,r,1);
			}
		}
	}
	rep(i,1,n){
		cout<<t.query(1,i,i)<<' ';
	} 
}

F

计算几何 exgcd

给整点(x,y)(x,y)(x,y),问能否找到一个整点(a,b)(a,b)(a,b)(0,0)(x,y)(a,b)(0,0)(x,y)(a,b)(0,0)(x,y)(a,b)组成的三角形面积为1.

首先考虑这个条件能转化成什么式子
在这里插入图片描述

也就是要解一个方程∣ay−bx∣=2|ay-bx|=2aybx=2。显然绝对值不重要,得到一组解之后取反就是绝对值相反的解。

也就是找到一组ay−bx=2ay-bx=2aybx=2的可行解。可以exgcdexgcdexgcd找到ay−bx=gcd(y,−x)ay-bx=gcd(y,-x)aybx=gcd(y,x)的一组可行解,设为ccc的话,带入可得ay−by=2ay-by=2ayby=2的解就是2c/gcd(y,−x)2c/gcd(y,-x)2c/gcd(y,x)

当然这需要能整除,所以根据gcdgcdgcd分讨。如果gcd>2gcd>2gcd>2,显然怎么线性组合也只能得到gcdgcdgcd的倍数,不可能凑出来222,无解。

一般的exgcdexgcdexgcd实现,就是返回gcdgcdgcd,而解通过传引用的方式返回

ll exgcd(ll a, ll b, ll &x, ll &y) {
    if (b == 0) {
        x = 1, y = 0;
        return a;
    }
    ll tx, ty, g = exgcd(b, a % b, tx, ty);
    x = ty, y = tx - a / b * ty;
    return g;
}
void solve(void){ 
	ll a, b;
    cin >> a >> b;
	if(gcd(a,b)>2){
		cout<<-1;
		return;
	} 
		ll x,y;
		exgcd(a,b,y,x);
		if(gcd(a,b)==1){
			cout<<-x*2<<' '<<y*2;
		}
		else{
			cout<<-x<<' '<<y;
		}
	
}
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐