您的位置:首页 > 其它

[BZOJ2527][POI2011]Meteors(整体二分)

2018-03-24 09:53 537 查看

题目:

我是超链接

题解:

对于每个国家来说,求出流星雨是第几次是一个妥妥的二分,但是这么多国家的话,我们用整体二分就行了

我们调用solve(1,k,1,n)就可以解决问题,即[1,k]范围内的流星雨可以解决[1,n]的国家

每次让在[l,mid]范围内的流星雨落下,回溯时要删除,二分询问的时候完成任务的国家放在左边,没完成的放在右边

特别要注意流星雨落下时l和r的大小。。

然后就是要开LL

代码:

#include <cstdio>
#include <algorithm>
#define LL long long
using namespace std;
const int N=300005;
struct hh{int hop,id,num;}st
;
struct lj{int l,r;LL k;}q
;
int tot,nxt
,point
,v
,m,n;LL c
,ans
;
void addline(int x,int y){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}
void add(int loc,LL v){for (int i=loc;i<=m+5;i+=i&(-i)) c[i]+=v;}
LL qurry(int loc)
{
LL ans=0;
for (int i=loc;i>=1;i-=i&(-i)) ans+=c[i];
return ans;
}
int cmp1(hh a,hh b){return a.num<b.num;}
void ef(int l,int r,int a,int b)
{
if (a>b) return;
int mid=(l+r)>>1;
for (int i=l;i<=mid;i++)
{
if (q[i].l<=q[i].r) add(q[i].l,q[i].k),add(q[i].r+1,-q[i].k);
else
{
add(q[i].l,q[i].k);add(m+1,-q[i].k);
add(1,q[i].k); add(q[i].r+1,-q[i].k);
}
}
if (l==r)
{
for (int x=a;x<=b;x++)
{
LL t=0;
for (int i=point[st[x].id];i;i=nxt[i])
{
t+=qurry(v[i]);
if (t>=st[x].hop) {ans[st[x].id]=l;break;}
}
if (t<st[x].hop) ans[st[x].id]=-1;
}

for (int i=l;i<=mid;i++)
{
if (q[i].l<=q[i].r) add(q[i].l,-q[i].k),add(q[i].r+1,q[i].k);
else
{
add(q[i].l,-q[i].k);add(m+1,q[i].k);
add(1,-q[i].k); add(q[i].r+1,q[i].k);
}
}
return;
}

int pa=0,pb=b-a+1;
for (int x=a;x<=b;x++)
{
LL t=0;
for (int i=point[st[x].id];i;i=nxt[i])
{
t+=qurry(v[i]);
if (t>=st[x].hop) {st[x].num=++pa;break;}
}
if (t<st[x].hop) st[x].num=++pb,st[x].hop-=t;
}
for (int i=l;i<=mid;i++)
{
if (q[i].l<=q[i].r) add(q[i].l,-q[i].k),add(q[i].r+1,q[i].k);
else
{
add(q[i].l,-q[i].k);add(m+1,q[i].k);
add(1,-q[i].k); add(q[i].r+1,q[i].k);
}
}
sort(st+a,st+b+1,cmp1);
ef(l,mid,a,a+pa-1);
ef(mid+1,r,a+pa,b);
}
int cmp(hh a,hh b){return a.id<b.id;}
int main()
{
scanf("%d%d",&n,&m);int x,k;
for (int i=1;i<=m;i++) scanf("%d",&x),addline(x,i);
for (int i=1;i<=n;i++) scanf("%lld",&st[i].hop),st[i].id=i;
scanf("%d",&k);
for (int i=1;i<=k;i++) scanf("%d%d%lld",&q[i].l,&q[i].r,&q[i].k);
ef(1,k,1,n);
sort(st+1,st+n+1,cmp);
for (int i=1;i<=n;i++)
if (ans[i]==-1) printf("NIE\n");else printf("%lld\n",ans[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: