[POI2011]MET-Meteors
Description:
给你一个环,每个点属于一个国家,每次进行区间加,问每个国家第几次加之后总和达到一个数
Hint:
\(n \le 3*10^5\)
Solution:
无语这题,要出整体二分就直接出,搞一个环来恶心人,还有那个国家,害我调好久
可以发现题中的第几次可以二分,预处理一下国家直接搞就行
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
const ll mxn=1e6+5;
ll n,m,k,cnt,hd[mxn];
inline ll read() {
char c=getchar(); ll x=0,f=1;
while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
return x*f;
}
inline void chkmax(ll &x,ll y) {if(x<y) x=y;}
inline void chkmin(ll &x,ll y) {if(x>y) x=y;}
struct Q {
ll id; ll p;
}q[mxn],tl[mxn],tr[mxn];
vector<ll > g[mxn];
ll ans[mxn],t[mxn],L[mxn],R[mxn],val[mxn];
ll lb(ll x) {return x&-x;}
void mod(ll x,ll y) {
while(x<=2*m) t[x]+=y,x+=lb(x);
}
ll query(ll x) {
ll res=0;
while(x) res+=t[x],x-=lb(x);
return res;
}
void solve(ll l,ll r,ll ql,ll qr) {
if(ql>qr) return ;
if(l==r) {
for(ll i=ql;i<=qr;++i) ans[q[i].id]=l;
return ;
}
ll mid=(l+r)>>1; ll lp=0,rp=0; //千万不能写外边
for(ll i=l;i<=mid;++i) mod(L[i],val[i]),mod(R[i]+1,-val[i]);
for(ll i=ql;i<=qr;++i) {
ll res=0;
for(ll j=0;j<g[q[i].id].size();++j) {
res+=query(g[q[i].id][j]+m)+query(g[q[i].id][j]);
if(res>q[i].p) break ;
}
if(res>=q[i].p) tl[++lp]=q[i];
else tr[++rp]=q[i],tr[rp].p-=res; //这里要写进去
}
for(ll i=l;i<=mid;++i) mod(L[i],-val[i]),mod(R[i]+1,val[i]);
for(ll i=ql;i<=ql+lp-1;++i) q[i]=tl[i-ql+1];
for(ll i=ql+lp;i<=qr;++i) q[i]=tr[i-lp-ql+1];
solve(l,mid,ql,ql+lp-1); solve(mid+1,r,ql+lp,qr);
}
int main()
{
n=read(); m=read();
for(ll i=1;i<=m;++i) g[read()].push_back(i);
for(ll i=1;i<=n;++i) q[i].p=read(),q[i].id=i; k=read();
for(ll i=1;i<=k;++i) L[i]=read(),R[i]=read(),val[i]=read();
for(ll i=1;i<=k;++i) if(R[i]<L[i]) R[i]+=m; solve(1,k+1,1,n);
for(ll i=1;i<=n;++i)
if(ans[i]==k+1) puts("NIE");
else printf("%lld\n",ans[i]);
return 0;
}