社区讨论

求助

P3997[SHOI2013] 扇形面积并参与者 2已保存回复 3

讨论操作

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

当前回复
3 条
当前快照
1 份
快照标识符
@mi4cwzg1
此快照首次捕获于
2025/11/18 17:14
3 个月前
此快照最后确认于
2025/11/20 04:05
3 个月前
查看原帖
我将每个扇形的半径视为扫描线中的 xx,其扫过的角度区间为 yy,并使用在扫描线中使用线段树二分求其面积。
代码:
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=1e5+5;
int n,m,k;
struct scanline{
	int x,y,w;
	inline bool operator<(const scanline &a)const{
		if(y!=a.y)return y<a.y;
		return w>a.w;
	}
}sl[MAXN*2];
vector<int> Q;
struct tree{
	int l,r,val,w;
}t[MAXN*4];
inline void push_up(int i){
	t[i].val=min(t[i*2].val,t[i*2+1].val);
}
inline void build(int i,int l,int r){
	t[i].l=l,t[i].r=r;
	if(l==r)return;
	int mid=(l+r)>>1;
	build(i*2,l,mid);
	build(i*2+1,mid+1,r);
}
inline void push_down(int i){
	if(t[i].w){
		t[i*2].w+=t[i].w,t[i*2].val+=t[i].w;
		t[i*2+1].w+=t[i].w,t[i*2+1].val+=t[i].w;
		t[i].w=0;
	}
}
inline void modify(int i,int l,int r,int w){
	if(Q[t[i].l-1]>=r||Q[t[i].r]<=l)return;
	if(Q[t[i].l-1]>=l&&Q[t[i].r]<=r){
		t[i].val+=w,t[i].w+=w;
		return;
	}
	push_down(i);
	modify(i*2,l,r,w),modify(i*2+1,l,r,w);
	push_up(i);
}
inline int query(int i,int sz){
	if(t[i].l==t[i].r){
		if(t[i].val<k)return sz;
		return Q[t[i].r];
	}
	push_down(i);
	if(t[i*2].val>=k)return query(i*2+1,Q[t[i*2].r]);
	else return query(i*2,sz);
}
signed main(){
//	freopen("1.in","r",stdin);
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>m>>k;
	Q.push_back(0);
	int tot=0;
	for(int i=1,r,a1,a2;i<=n;i++){
		cin>>r>>a1>>a2;
		if(a1<a2){
			sl[++tot]=(scanline){r,a1,1};
			sl[++tot]=(scanline){r,a2,-1};
		}else{
			sl[++tot]=(scanline){r,a1,1};
			sl[++tot]=(scanline){r,m,-1};
			sl[++tot]=(scanline){r,-m,1};
			sl[++tot]=(scanline){r,a2,-1};
		}
		Q.push_back(r);
	}
	sort(Q.begin(),Q.end());
	Q.erase(unique(Q.begin(),Q.end()),Q.end());
	sort(sl+1,sl+1+tot);
	build(1,1,Q.size()-1);
	int sum=0;
	sl[tot+1].y=m;
	for(int i=1;i<=tot;i++){
		modify(1,0,sl[i].x,sl[i].w);
		int alpha=(sl[i+1].y-sl[i].y),r=query(1,0);
		sum+=alpha*r*r;
	}
	cout<<sum;
}
本人使用了如下随机数据生成器生成数据:
CPP
#include<bits/stdc++.h>
using namespace std;
int n=10000,m=1000000,k;
mt19937 rd(time(nullptr));
inline int Rand(int l,int r){
	int tmp=rd()%(r-l+1);
	return tmp+l;
}
signed main(){
	freopen("1.in","w",stdout);
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	k=Rand(1,5000);
	cout<<n<<" "<<m<<" "<<k<<'\n';
	for(int i=1;i<=n;i++){
		int a1=Rand(-m,m),a2=Rand(-m,m);
		cout<<Rand(1,n)<<" "<<a1<<" "<<a2<<'\n';
	}
}
并在本地使用 @LPA20020220 的题解@Gmt丶FFF 的题解对随机数据生成正解进行对拍。进行约 50 次对拍后答案均相同,但提交得分始终只有 40 分。

回复

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

正在加载回复...