题解:P3527 [POI 2011] MET-Meteors

link

发现暴力没什么前途,考虑一种很甜筒的做法,对每个国家进行二分,然后处理每场陨石雨。

显然这样复杂度会慢很多,但是可以发现这些国家可以一起二分,即整体二分。设 \(solve(country,l,r)\) 函数处理二分的国家集合为 \(country\),答案在区间 \([l,r]\)中。

我们进行时间在 \([l,mid]\) 中的操作(用树状数组维护),完成后对于已经满足条件的国家,用 \(solve(country_l,l,mid)\) 处理;对于不满足条件的,则将其减去 \([l,mid]\) 所提供的陨石的和,在 \(solve(country_r,mid+1,r)\) 中处理。

发现递归最多 \(O(\log m)\) 层,每层的 \(\sum|country|=n\)\(\sum r-l+1=k\),所以每层的复杂度为 \(O((n+m)\log n)\),总复杂度 \(O((n+m)\log n\log m)\)

注意每层递归之前将树状数组清空,同时计算 \([l,mid]\) 所提供的陨石的和时,因为每个国家可能有多个空间站,可能会爆 long long,可以加特判或开 unsigned

Code:

#include<iostream>
#include<vector>
#define lowbit(x) ((x)&(-(x)))
#define rep(i,l,r) for(int i=(l);i<=(r);i++)
#define per(i,l,r) for(int i=(l);i>=(r);i--)
using namespace std;
const int maxn=3e5+5;
typedef unsigned long long ll;
ll sum[maxn];
int ans[maxn],ap[maxn],ed[maxn],tot,in,im,ik;
struct node{
	int l,r,a;
}an[maxn<<1];
vector<int> O[maxn];
inline void modify(int pos,int v){
	for(int v1=pos;v1<=im;v1+=lowbit(v1))sum[v1]+=v;
} 
inline ll query(int pos){
	ll res=0;
	for(int v1=pos;v1;v1-=lowbit(v1))res+=sum[v1];
	return res;
}
inline void solve(vector<int> &v,int l,int r){
	if(l==r){
		for(int p:v)ans[p]=l;
		return;
	}
	int mid=l+r>>1;
	rep(v1,ed[l-1]+1,ed[mid]){
		modify(an[v1].l,an[v1].a);
		modify(an[v1].r+1,-an[v1].a);
	}
	vector<int> lv,rv;
	for(int p:v){
		ll t=0;
		for(int v2:O[p]){
			t+=query(v2);
		}
		if(t>=ap[p]){
			lv.push_back(p);
		}
		else{
			ap[p]-=t;
			rv.push_back(p);
		}
	}
	rep(v1,ed[l-1]+1,ed[mid]){
		modify(an[v1].l,-an[v1].a);
		modify(an[v1].r+1,an[v1].a);
	}
	solve(lv,l,mid);
	solve(rv,mid+1,r);
}
int main()
{
	cin>>in>>im;
	rep(v1,1,im){
		int io;
		scanf("%d",&io);
		O[io].push_back(v1);
	}
	rep(v1,1,in)scanf("%d",ap+v1);
	scanf("%d",&ik);
	rep(v1,1,ik){
		int il,ir,ia;
		scanf("%d %d %d",&il,&ir,&ia);
		if(il<=ir)an[++tot]={il,ir,ia};
		else{
			an[++tot]={il,im,ia};
			an[++tot]={1,ir,ia};
		}
		ed[v1]=tot;
	}
	ed[ik+1]=tot;
	vector<int> st;
	rep(v1,1,in)st.push_back(v1);
	solve(st,1,ik+1);
	rep(v1,1,in){
		if(ans[v1]>ik)printf("NIE\n");
		else printf("%d\n",ans[v1]);
	}
	return 0;
}
posted @ 2025-07-13 20:50  FugiPig  阅读(15)  评论(0)    收藏  举报