社区讨论

84分求调,悬赏关注

P7990[USACO21DEC] Closest Cow Wins S参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mlt5asc7
此快照首次捕获于
2026/02/19 15:34
3 周前
此快照最后确认于
2026/02/22 22:05
2 周前
查看原帖
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
map<int,int> mp;
int k2,k=0,m,n,p[1000005],q[1000005],d[1000005],lsh[1000005],tot=0,b[1000005];
struct A {
	int l,r,w;
} a[1000005];
bool cmp(A a,A b) {
	return a.l<b.l;
}
struct B {
	int sz,wz;
};
bool operator <(B x,B y){
	return x.sz<y.sz;
}
struct C {
	int l,r,lz;
	B mes;
} tr[4000005];
void makelazy(int p,int x) {
	tr[p].lz+=x;
	tr[p].mes.sz+=x;
}
void pushup(int p) {
	tr[p].mes=max(tr[p<<1].mes,tr[p<<1|1].mes);
}
void pushdown(int p) {
	makelazy(p<<1,tr[p].lz);
	makelazy(p<<1|1,tr[p].lz);
	tr[p].lz=0;
}
void build(int p,int l,int r) {
	tr[p].l=l,tr[p].r=r,tr[p].lz=0;
	if(l==r) {
		tr[p].mes.sz=0,tr[p].mes.wz=l;
		return;
	}
	int mid=l+r>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	pushup(p);
}
void change(int p,int l,int r,int k) {
	if(l<=tr[p].l&&tr[p].r<=r) {
		makelazy(p,k);
		return;
	}
	if(tr[p].l>r||tr[p].r<l)return;
	pushdown(p);
	change(p<<1,l,r,k);
	change(p<<1|1,l,r,k);
	pushup(p);
}
B search(int p,int l,int r) {
	if(l<=tr[p].l&&tr[p].r<=r)return tr[p].mes;
	if(tr[p].l>r||tr[p].r<l)return {(int)-1e18,(int)-1e18};
	pushdown(p);
	return max(search(p<<1,l,r),search(p<<1|1,l,r));
}
struct D {
	int wz,bh;
};
bool operator <(D x,D y) {
	if(x.wz!=y.wz)return x.wz<y.wz;
	else return a[x.bh].l<a[y.bh].l;
}
struct E {
	int wz,bh;
};
bool operator <(E x,E y) {
	if(x.wz!=y.wz)return x.wz<y.wz;
	else return a[x.bh].r<a[y.bh].r;
}
set<D> s1;
set<E> s2;
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>k2>>m>>n;
	for(int i=1; i<=k2; i++) {
		int x,y;
		cin>>x>>y;
		if(!mp[x])mp[x]=++k,p[mp[x]]=x;
		q[mp[x]]+=y;
	}
	for(int i=1; i<=m; i++)cin>>d[i];
	sort(d+1,d+m+1);
	d[0]=-1e18,d[m+1]=1e18;
	for(int i=1; i<=k; i++) {
		int x=min(d[lower_bound(d+1,d+m+1,p[i])-d]-p[i],p[i]-d[upper_bound(d+1,d+m+1,p[i])-d-1]);
		a[i].l=p[i]-x+1,a[i].r=p[i]+x-1,a[i].w=q[i];
		lsh[++tot]=a[i].l,lsh[++tot]=a[i].r;
	}
	sort(lsh+1,lsh+tot+1);
	tot=unique(lsh+1,lsh+tot+1)-lsh-1;
	build(1,1,tot);
	for(int i=1; i<=k; i++) {
		a[i].l=lower_bound(lsh+1,lsh+tot+1,a[i].l)-lsh,a[i].r=lower_bound(lsh+1,lsh+tot+1,a[i].r)-lsh;
		if(a[i].l>a[i].r)continue;
		change(1,a[i].l,a[i].r,a[i].w);
		s1.insert({a[i].r,i});
		s2.insert({a[i].l,i});
	}
	a[k+1].l=-1e18,a[k+1].r=1e18;
	int ans=0;
	for(int i=1; i<=n; i++) {
		B x=search(1,1,tot);
		if(x.sz==-1e18)break;
		ans+=x.sz;
		auto it1=s1.lower_bound({x.wz,k+1});
		auto it2=s2.upper_bound({x.wz,k+1});
		while(it1!=s1.end()&&a[it1->bh].l<=x.wz)change(1,a[it1->bh].l,a[it1->bh].r,-a[it1->bh].w*(1-b[it1->bh])),b[it1->bh]=1,it1++;
		while(it2!=s2.begin()&&a[(--it2)->bh].r>=x.wz)change(1,a[it2->bh].l,a[it2->bh].r,-a[it2->bh].w*(1-b[it2->bh])),b[it2->bh]=1;
	}
	cout<<ans;
	return 0;
}
离散化后,线段树维护区间最大值,每回选择所得最大的位置。由于区间相互不严格包含(只有端点可能重合),使用 set 维护区间,每回在线段树上删除包含已经选了的这个位置的区间的贡献。只有84分,WA了9,12,13,17。

回复

0 条回复,欢迎继续交流。

正在加载回复...