分治或者叫整体二分。
对于分治的每一次将国家向左或向右分成两部分,因为要求的是个最小前缀,所有左半部分的陨石不满足就将这个国家分到有半部分,满足就说明在左半部分的某处。
#include <bits/stdc++.h>
#define ll long long
#define int ll
#define ls a[p].l
#define rs a[p].r
#define re register
#define pb push_back
#define pir pair<int,int>
#define f(a,x,i) for(int i=a;i<=x;i++)
#define fr(a,x,i) for(int i=a;i>=x;i--)
using namespace std;
const int N=3e5+10;
const int M=8e6+10;
const int mod=1e9+7;
mt19937 rnd(251);int n,m;
int ans[N];
int lim=1e18;vector<int> pos[N];
int p[N];struct BIT{int lb(int x){return (x&-x);}int t[N];void set(int x){for(;x<=m;x+=lb(x)) t[x]=0;}void update(int x,int k){for(;x<=m;x+=lb(x)) t[x]+=k,t[x]=min(t[x],lim);} void add(int l,int r,int x){update(l,x);update(r+1,-x);}int query(int x){int sum=0;for(;x;x-=lb(x)) sum+=t[x],sum=min(sum,lim);return sum;}} bit;void solve(vector<int> &country,auto &range,int L,int R){if(L==R){for(int x:country){ans[x]=L;}return;}if(country.size()==0) return;int mid=(L+R)>>1;vector<tuple<int,int,int,int>> lrange,rrange;for(auto &[l,r,x,i]:range){if(i>mid){rrange.push_back({l,r,x,i});continue;}bit.add(l,r,x);lrange.push_back({l,r,x,i});}vector<int> countryl,countryr;for(auto &x:country){int sum=0;for(int y:pos[x]) sum+=bit.query(y),sum=min(sum,lim);if(sum>=p[x]) countryl.push_back(x);else countryr.push_back(x),p[x]-=sum;}for(auto &[l,r,x,i]:lrange){bit.set(l);bit.set(r+1);}solve(countryl,lrange,L,mid);solve(countryr,rrange,mid+1,R);
}signed main(){// freopen("a.in","r",stdin);// freopen("a.out","w",stdout);ios::sync_with_stdio(0);cin.tie(nullptr); cin>>n>>m;for(int i=1;i<=m;i++){int x;cin>>x;pos[x].push_back(i);}for(int i=1;i<=n;i++){cin>>p[i];}int k;cin>>k;vector<tuple<int,int,int,int>> range;for(int i=1;i<=k;i++){int l,r,x;cin>>l>>r>>x;if(l<=r){range.push_back({l,r,x,i});}else{range.push_back({l,m,x,i});range.push_back({1,r,x,i});}}vector<int> country(n);iota(country.begin(),country.end(),1);solve(country,range,0,k+1);for(int i=1;i<=n;i++){if(ans[i]<=k){cout<<ans[i]<<"\n";}else{cout<<"NIE\n";}}return 0;
}