bzoj2527(整体二分)

第一道整体二分,实际上就是锻炼分治思想

 

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=300005;
const ll inf=1e9+10;

int n,m,k;
struct aa
{
	ll p;int ans; 
}c[N];
//
int head[N],to[N],pre[N],tot;
void addedge(int u,int v)
{
	to[++tot]=v;pre[tot]=head[u];head[u]=tot;
}
///
struct aaa
{
	int l,r;ll sum;bool clear;
}a[N*4];
void build(int i,int l,int r)
{
	a[i].l=l,a[i].r=r;
	if (l==r) return ;
	int mid=(l+r)>>1;
	build(i<<1,l,mid);
	build(i<<1|1,mid+1,r);
}
void down(int i)
{
	if (a[i].clear)
	{
		a[i<<1].sum=a[i<<1|1].sum=0;
		a[i<<1].clear=a[i<<1|1].clear=true;
		a[i].clear=false;
	}
}
void updata(int i,int l,int r,ll add)
{
	if (a[i].l==l&&a[i].r==r) {a[i].sum+=add;return;}
	int mid=(a[i].l+a[i].r)>>1;
	down(i);
	if (r<=mid) updata(i<<1,l,r,add);
	else if (mid<l) updata(i<<1|1,l,r,add);
	else updata(i<<1,l,mid,add),updata(i<<1|1,mid+1,r,add);
}
ll query(int i,int pos)
{
	if (a[i].l==a[i].r) return a[i].sum;
	int mid=(a[i].l+a[i].r)>>1;
	down(i);
	if (pos<=mid) return query(i<<1,pos)+a[i].sum;
	return query(i<<1|1,pos)+a[i].sum;
}
/
struct aaaa
{
	int l,r;ll add;
}t[N];
int q[N],tmp[N];

void updata(int i)
{
	if (t[i].l<=t[i].r) updata(1,t[i].l,t[i].r,t[i].add);
	else updata(1,t[i].l,m,t[i].add),updata(1,1,t[i].r,t[i].add);
}
void clear()
{
	a[1].sum=0;a[1].clear=true;
}
void work(int tl,int tr,int l,int r)
{
	if (l>r) return ; 
	if (tl==tr) 
	{
		for (int i=l;i<=r;i++) c[q[i]].ans=tl;
		return ;
	}
	int mid=(tl+tr)>>1,ll=l,rr=r;
	clear();
	for (int i=tl;i<=mid;i++) updata(i);
	for (int i=l;i<=r;i++)
	{
		long long ans=0;
		for (int j=head[q[i]];j;j=pre[j]) 
		{
			ans+=query(1,to[j]);
			if (ans>inf) break;
		}
		if (ans>=c[q[i]].p) tmp[ll++]=q[i];else tmp[rr--]=q[i],c[q[i]].p-=ans;
	}
	for (int i=l;i<=r;i++) q[i]=tmp[i];
	work(tl,mid,l,rr);
	work(mid+1,tr,ll,r);
}
int main()
{
	scanf("%d%d",&n,&m);
	int x;
	for (int i=1;i<=m;i++)
	{
		scanf("%d",&x);
		addedge(x,i);
	}
	for (int i=1;i<=n;i++) scanf("%lld",&c[i].p),q[i]=i;
	scanf("%d",&k);
	for (int i=1;i<=k;i++) scanf("%d%d%lld",&t[i].l,&t[i].r,&t[i].add);
	t[k+1].l=1,t[k+1].r=m,t[k+1].add=1e9;
	build(1,1,m);
	work(1,k+1,1,n);
	
	for (int i=1;i<=n;i++) 
	if (c[i].ans==k+1) printf("NIE\n");else printf("%d\n",c[i].ans);
	return 0;
}
/*
6 6
1 2 3 4 5 6
10 10 10 10 10 10
3
1 3 5
4 6 6
2 4 6

*/


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值