AtCoder Beginner Contest 449题解

近期这几套atcoder里最难的一套。

D - Make Target 2

官方

D - Make Target 2 题解由 en_translator 提供


为了方便处理 \(\max(|x|, |y|)\) 这个表达式,我们用 \(|x| > |y|\)\(|x| \leq |y|\) 来计算,最后求和得出答案。

下面,我们将介绍如何计算带有 \(|x| > |y|\) 的数。带有 \(|x| \leq |y|\) 的数也可以同样计算。

\(|x| > |y|\)\(\max(|x|, |y|) = |x|\) 时。因此,我们可以遍历 \(L \leq x \leq R\) 内的所有偶数 \(x\) ,并为每个 \(x\) 找出带有 \(|x| > |y|\)\(D \leq y \leq U\)\(y\) 的个数。由于 \(|x| > |y|\) 等价于 \(-|x| < y < |x|\) ,对于固定的 \(x\) ,要计算的整数 \(y\)\(\max(-|x| + 1, D) \leq y \leq \min(|x| - 1, U)\) 之内。这样的 \(y\) 的个数可以表示为 \(\max(0, \min(|x| - 1, U) - \max(-|x| + 1, D) + 1)\) ,每个 \(x\) 的计算时间为 \(O(1)\) 。因此,可以在 \(O(X)\) 个时间内计算出 \(|x| > |y|\) 个,其中 \(X = R - L\) 个。

int main() {
	int l, r, d, u;
	cin >> l >> r >> d >> u;
	ll ans = 0;

	// |x| > |y|
	for (int x = l; x <= r; x++) {
		if (x % 2 == 0) {
			int D = max(d, -abs(x) + 1);
			int U = min(u, abs(x) - 1);
			int C = U - D + 1;
			ans += max(C, 0);
		}
	}

	// |x| <= |y|
	for (int y = d; y <= u; y++) {
		if (y % 2 == 0) {
			int L = max(l, -abs(y));
			int R = min(r, abs(y));
			int C = R - L + 1;
			ans += max(C, 0);
		}
	}

	cout << ans << '\n';
}

E - A += v

标答没看懂,所以我选择直接可持久化线段树硬上。

int n,m,q,a[N],cnt[N],mx;
vector<int>vec[N];
int len[N],s[N];
vector<int>tmp[750];
int rt[N];
struct HTree{
    struct node{
        int ls,rs;
        int sum;
    }tr[N<<5];
    int cnt;
	inline void change(int &k,int pre,int l,int r,int x,int y){
        k=++cnt;
        tr[k]=tr[pre];tr[k].sum++;
        if(l==r)return;
        int mid=(l+r)>>1;
        if(x<=mid)change(tr[k].ls,tr[pre].ls,l,mid,x,y);
        if(y>mid)change(tr[k].rs,tr[pre].rs,mid+1,r,x,y);
    }
    inline int ask(int ll,int rr,int l,int r,int kth){
	    int x=tr[tr[rr].ls].sum-tr[tr[ll].ls].sum;
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(x>=kth) return ask(tr[ll].ls,tr[rr].ls,l,mid,kth);
        return ask(tr[ll].rs,tr[rr].rs,mid+1,r,kth-x);
    }
}T;
signed main() {
	std::ios::sync_with_stdio(0),cin.tie(0);
	cin>>n>>m;
	up(i,1,n){
		cin>>a[i];
		++cnt[a[i]];
		mx=max(mx,cnt[a[i]]);
	}
	up(i,1,m)vec[cnt[i]].push_back(i);
	len[0]=s[0]=vec[0].size();
	for(int i=1; i<=mx; ++i) {
		len[i]=len[i-1]+vec[i].size();
		s[i]=s[i-1]+len[i];
	}
	int k=0;
	for(int i=0; i<=mx; ++i) {
		for(auto v:vec[i]) {
			++k;
			T.change(rt[k],rt[k-1],1,m,v,v);
		}
	}
	cin>>q;
	while(q--) {
		int x;
		cin>>x;
		if(x<=n)cout<<a[x]<<"\n";
		else if(x>mx*m){
			if(x%m==0) cout<<m<<"\n";
			else cout<<x%m<<"\n";
		} 
        else{
			x-=n;
			int l=0,r=mx,mid,c=mx;
			while(l<=r) {
				mid=(l+r)>>1;
				if(x<=s[mid]) c=mid,r=mid-1;
				else l=mid+1;
			}
			if(c) x-=s[c-1];
			cout<<T.ask(rt[0],rt[len[c]],1,m,x)<<"\n";
		}
	}
	return 0;
}

F - Grid Clipping

正难则反,运用容斥和扫描线。

int H,W,h,w,n;
struct linee {
	int l, r, h,mark;
	bool operator <(const linee&rhs)const{
        if(h == rhs.h)return mark > rhs.mark;
        return h < rhs.h;
    }
} line[N<<1];
int X[N<<1];
struct node{
    int l, r, sum,c,len;
}tr[N<<4];

inline void push_up(int k) {
	int l = tr[k].l, r = tr[k].r;
	if(tr[k].sum)tr[k].len = X[r + 1] - X[l];
	else tr[k].len = tr[lc].len + tr[rc].len;
}
inline void build(int k,int l,int r){
    tr[k].l=l;tr[k].r=r;
    if(l==r)return;
    int mid=(l+r)>>1;
    build(lc,l,mid);
    build(rc,mid+1,r);
    push_up(k);
}
inline void ask(int k, int L, int R, int c) {
	int l = tr[k].l, r = tr[k].r;
	if(X[l] >= R || X[r + 1] <= L)return;
	if(L <= X[l] && X[r + 1] <= R) {
		tr[k].sum += c;
		push_up(k);
		return;
	}
	ask(lc, L, R, c);
	ask(rc, L, R, c);
	push_up(k);
}
void solve(){
	cin>>H>>W>>h>>w>>n;
    int u,v;
	if (!n){
		cout << (H - h + 1) * (W - w + 1);
		return;
	}
	for(int i=1,x1,y1,x2,y2;i<=n;i++){
        cin>>u>>v;
		x1=max(1ll,u-h+1);y1=max(1ll,v-w+1);
        x2=min(u,H-h+1)+1;y2=min(v,W-w+1)+1;
        line[i * 2 - 1] ={x1, x2, y1, 1};
		line[i * 2] = {x1, x2, y2,-1};
		X[i * 2 - 1] = x1, X[i * 2] = x2;
    }
    n <<= 1;
	sort(line + 1, line + n + 1);
	sort(X + 1, X + n + 1);
	int tot = unique(X + 1, X + n + 1) - X - 1;
	build(1, 1, tot - 1);
    int res = 0,pre=0;;
	for(int i = 1; i < n; i++) {
		ask(1, line[i].l, line[i].r, line[i].mark);
		res += tr[1].len * (line[i + 1].h - line[i].h);
	}
	cout<<(H-h+1)*(W-w+1)-res;
}

posted @ 2026-03-25 23:29  LiQXing  阅读(10)  评论(0)    收藏  举报