显然答案具有单调性,对于一个国家,如果第 \(mid\) 次后达到了要求,那么对于大于 \(mid\) 的第 \(r\) 次后也肯定达到了要求。
对于单个一个国家,可以二分流星雨的次数。复杂度 \(O(m\log k)\)。
但是对于 \(n\) 个国家的情况,复杂度即为 \(O(nm\log k)\) 很快啊不能满足要求。
这提示我们使用整体二分,把所有国家放在一起二分。
具体实现:
细节:
code:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
bool ks;
int n,m,T,ans[300010];
int Lpos[300010],Rpos[300010],p[300010],a[300010];
LL c[300010],asktemp[300010];
vector<int>have[300010];
struct Q
{int bel,pos;}q[300010],lq[300010],rq[300010];
bool js;
inline int read()
{
int x=0,w=0;char ch=0;
while(!isdigit(ch)){w|=ch==‘-‘;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return w?-x:x;
}
void change(int x,int y)
{for(;x<=m;x+=x&-x)c[x]+=y;}
LL ask(int x,LL y=0)
{for(;x;x-=x&-x)y+=c[x];return y;}
void calc(int L,int R,int st,int ed)
{
if(st>ed)return;
if(L==R){
for(int i=st;i<=ed;i++)
ans[q[i].bel]=L;
return;
}
int M=(L+R)>>1,l=0,r=0;
for(int i=L;i<=M;i++)
if(Lpos[i]<=Rpos[i]){
change(Lpos[i],a[i]);
change(Rpos[i]+1,-a[i]);
}else{
change(1,a[i]);
change(Rpos[i]+1,-a[i]);
change(Lpos[i],a[i]);
}
for(int i=st;i<=ed;i++){
if(asktemp[q[i].bel]==-1){
asktemp[q[i].bel]=0;
for(int j=0;j<int(have[q[i].bel].size());j++){
asktemp[q[i].bel]+=ask(have[q[i].bel][j]);
if(asktemp[q[i].bel]>=p[q[i].bel])break;
}
}
if(asktemp[q[i].bel]>=p[q[i].bel])lq[++l]=q[i];
else rq[++r]=q[i];
}
for(int i=L;i<=M;i++)
if(Lpos[i]<=Rpos[i]){
change(Lpos[i],-a[i]);
change(Rpos[i]+1,a[i]);
}else{
change(1,-a[i]);
change(Rpos[i]+1,a[i]);
change(Lpos[i],-a[i]);
}
for(int i=st;i<=ed;i++){
if(i-st+1<=l)q[i]=lq[i-st+1];
else{
q[i]=rq[i-st+1-l];
if(asktemp[q[i].bel]!=-1)
p[q[i].bel]-=asktemp[q[i].bel];
}
asktemp[q[i].bel]=-1;
}
calc(L,M,st,st+l-1);
calc(M+1,R,st+l,ed);
}
int main()
{
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
// cout<<(&js-&ks)/1024./1024<<‘\n‘;
n=read();m=read();
for(int i=1;i<=m;i++)
have[q[i].bel=read()].push_back(q[i].pos=i);
for(int i=1;i<=n;i++)p[i]=read();
T=read();
for(int i=1;i<=T;i++)
Lpos[i]=read(),Rpos[i]=read(),a[i]=read();
memset(asktemp,-1,sizeof asktemp);
memset(ans,0x3f,sizeof ans);
calc(1,T+1,1,m);
for(int i=1;i<=n;i++)
if(ans[i]<=T)printf("%d\n",ans[i]);
else printf("NIE\n");
}
原文:https://www.cnblogs.com/zYzYzYzYz/p/14493428.html