【题解】P3527 [POI 2011] MET-Meteors
分治或者叫整体二分。
对于分治的每一次将国家向左或向右分成两部分,因为要求的是个最小前缀,所有左半部分的陨石不满足就将这个国家分到有半部分,满足就说明在左半部分的某处。
#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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具