代码源挑战赛 Round 47

比赛链接

A

简单题

B

在题目条件下,如果 \(|s| = 1\) 则答案为 \(1\),否则判一下最大的数字。

C

显然可以对于每一位分别考虑,记 \(\operatorname {dist} (x, y)\) 表示 \(x, y\) 在模 \(26\) 意义下的距离,数字串就相当于在 \(0\)\(9\) 之间建立代价为 \(1\) 的传送门。从 \(x\)\(y\) 的最小代价有三种情况:

  1. 不经过传送门:\(\operatorname {dist} (x, y)\)
  2. 传送 \(0 \rightarrow 9\)\(\operatorname {dist} (x, 0) + 1 + \operatorname {dist} (9, y)\)
  3. 传送 \(9 \rightarrow 0\)\(\operatorname {dist} (x, 9) + 1 + \operatorname {dist} (0, y)\)

D

使用 \((n - x + 1) \sim n\) 构造一条点数为 \(x\) 的链,然后把剩余点都接 \(n\) 上就可以了。

E

使用魔法的肯定是一段前缀 + 一段后缀,且长度之和为 \(k\),枚举前缀长度后即可 \(\text O (1)\) 计算,大约是这样写:

    int le=min(a[1]+x,a[i+1]),ri=max(a[n]-x,a[n-(k-i)]);
    ans=min(ans,max((ri-le+1)/2,0));

F

先处理出所有 \(s _ i\)。考虑 dfs,把所有 \(x\) 的祖先挂到树状数组上,分讨一下正负性。写的时候需要离散化一下。

G

发现这个东西可以用平衡树维护。放一下 FHQ-Treap 代码:

#include<cstdio>
#include<random>
#define N 1200005
using namespace std;

typedef long long ll;
int n,q,a[N];
mt19937 rnd(random_device{}());
struct fhq {
	int tot,r;
	struct treap {
		int lc,rc,cnt,siz,pri;
		ll c,val,sum,tag;
		#define lc(p) tr[p].lc
		#define rc(p) tr[p].rc
		#define cnt(p) tr[p].cnt
		#define siz(p) tr[p].siz
		#define pri(p) tr[p].pri
		#define c(p) tr[p].c
		#define val(p) tr[p].val
		#define sum(p) tr[p].sum
		#define tag(p) tr[p].tag
		treap() {
			pri=rnd();
		}
	} tr[N];
	int node(int u,ll v) {
		tot++;
		cnt(tot)=siz(tot)=u,c(tot)=v,val(tot)=sum(tot)=u*v;
		return tot;
	}
	void update(int p) {
		siz(p)=siz(lc(p))+cnt(p)+siz(rc(p));
		sum(p)=sum(lc(p))+val(p)+sum(rc(p));
	}
	void inc(int p,ll c) {
		c(p)+=c,val(p)+=c*cnt(p),sum(p)+=c*siz(p),tag(p)+=c;
	}
	void spread(int p) {
		if(tag(p)) {
			if(lc(p)) inc(lc(p),tag(p));
			if(rc(p)) inc(rc(p),tag(p));
			tag(p)=0;
		}
	}
	void split(int p,int &L,int &R,int k) {
		if(!p) {L=R=0; return;}
		spread(p);
		if(k<=siz(lc(p))) R=p,split(lc(p),L,lc(p),k);
		else L=p,split(rc(p),rc(p),R,k-siz(lc(p))-cnt(p));
		update(p);
	}
	int merge(int p,int q) {
		if(!p||!q) return p|q;
		if(pri(p)<pri(q)) {
			spread(p),rc(p)=merge(rc(p),q);
			return update(p),p;
		} else {
			spread(q),lc(q)=merge(p,lc(q));
			return update(q),q;
		}
	}
	int ask(int p) {
		return rc(p)?ask(rc(p)):cnt(p);
	}
	void sp(int k) {
		int L,R; split(r,L,R,k);
		if(siz(L)>k) {
			int ss=siz(L)-ask(L),mid; split(L,L,mid,ss);
			int sl=k-siz(L),sr=cnt(mid)-sl;
			L=merge(L,node(sl,c(mid))),R=merge(node(sr,c(mid)),R);
		}
		r=merge(L,R);
	}
	void insert(int k,int c,int v) {
		sp(k);
		int L,R; split(r,L,R,k);
		r=merge(merge(L,node(c,v)),R);
	}
	ll pop(int k) {
		sp(k);
		int R; split(r,r,R,k);
		return sum(R);
	}
	void add(int x,int y,ll c) {
		sp(x-1),sp(y);
		int L,R,mid; split(r,L,R,y),split(L,L,mid,x-1);
		inc(mid,c);
		r=merge(merge(L,mid),R);
	}
	ll ask(int x,int y) {
		sp(x-1),sp(y);
		int L,R,mid; split(r,L,R,y),split(L,L,mid,x-1);
		ll res=sum(mid);
		r=merge(merge(L,mid),R);
		return res;
	}
} t1;
int main() {
	scanf("%*d%d%d",&n,&q);
	for(int i=1,x;i<=n;i++) {
		scanf("%d",&x),t1.insert(i-1,1,x);
	}
	for(int i=1,op,x,y,z;i<=q;i++) {
		scanf("%d%d%d",&op,&x,&y);
		if(op==1) {
			scanf("%d",&z),t1.insert(x,y,z);
			printf("%lld\n",t1.pop(n));
		}
		else if(op==2) {
			scanf("%d",&z),t1.add(x,y,z);
		}
		else {
			printf("%lld\n",t1.ask(x,y));
		}
	}
	return 0;
}
posted @ 2026-01-23 22:21  yemuzhe  阅读(13)  评论(0)    收藏  举报