1. 程式人生 > >POI2011 MET-Meteors

POI2011 MET-Meteors

define ret printf d+ post 一個 poi c++ esp

首先看上來就可以進行二分,但是答案是n個,所以我們進行整體二分,每次分成兩個集合,一個集合可以完成,一個不可以,然後繼續二分即可。

學習了Vergil學長的做法,偷懶用了vector,然後luogu上90分,懶得用數組去模擬實現了(都是細節)——by VANE

#include<bits/stdc++.h>
using namespace std;
#define N 300005
long long c[N];
int n,m,k,goal[N],ans[N];
int L[N],R[N],A[N],vis_cnt;
int vis[N];
vector<int> S,g[N];
void clear(int x) { if(vis[x]==vis_cnt) return; vis[x]=vis_cnt; c[x]=0; } inline int read() { int x=0;char ch=getchar();int f=1; while(ch<0||ch>9) {if(ch==-) f=-f;ch=getchar();} while(ch>=0&&ch<=9) {x=x*10+ch-0;ch=getchar();} return x*f; } void add(int
x,int z) { for(;x<=m;x+=x&-x) { clear(x); c[x]+=z; } } long long sum(int x) { long long w=0; for(;x;x-=x&-x) { clear(x); w+=c[x]; } return w; } void solve(int l,int r,vector<int> S) { if(l==r) { int siz=S.size();
for(int j=0;j<siz;++j) ans[S[j]]=l; return; } int mid=l+r>>1; vis_cnt++; for(int i=l;i<=mid;++i) { if(L[i]<=R[i]) { add(L[i],A[i]); add(R[i]+1,-A[i]); } else { add(L[i],A[i]); add(1,A[i]); add(R[i]+1,-A[i]); } } int siz=S.size(); vector<int> S1,S2; for(int j=0;j<siz;++j) { int u=S[j]; int sizz=g[u].size(); long long w=0; bool flag=0; for(int b=0;b<sizz;++b) { w+=sum(g[u][b]); if(w>=goal[u]) { S1.push_back(u); flag=1; break; } } if(!flag) { S2.push_back(u); goal[u]-=w; } } if(S1.size()) solve(l,mid,S1); if(S2.size()) solve(mid+1,r,S2); } int main() { n=read();m=read(); for(int i=1;i<=m;++i) g[read()].push_back(i); for(int i=1;i<=n;++i) goal[i]=read(); k=read(); for(int i=1;i<=k;++i) { L[i]=read(); R[i]=read(); A[i]=read(); } for(int i=1;i<=n;++i) S.push_back(i); solve(1,k+1,S); for(int i=1;i<=n;++i) if(ans[i]==k+1) puts("NIE"); else printf("%d\n",ans[i]); return 0; }

POI2011 MET-Meteors