整体二分

#include <stdio.h>
#include <vector>
#include <cstring>
using namespace std;


const int maxN=300010;
struct Tnode{
int l,r,c;
}p[maxN];
vector <int> e[maxN];
long long tree[maxN];
struct Tpoint{
long long x;
int y;
}a[maxN],b[maxN];
long long ans[maxN];
int n,m,k;
int add(int pos,int x)
{
for (int i=pos; i<=m; i+=i&(-i))tree[i]+=(long long)x;
}
int query(int pos)
{
long long ret=0;
for (int i=pos; i>0; i-=i&(-i))ret+=tree[i];
return ret;
}
void solve (int l,int r,int L,int R)
{
if (l>r || L>R)return ;
int mid=(l+r)/2;
for (int i=l; i<=mid; i++)
{
// printf("p[%d] l:%d r:%d c:%d\n",i,p[i].l,p[i].r,p[i].c);
if (p[i].l<=p[i].r) add(p[i].l,p[i].c),add(p[i].r+1,-p[i].c);
else add(1,p[i].c),add(p[i].r+1,-p[i].c),add(p[i].l,p[i].c);
}
int t1=L,t2=R;
// printf( "%d ",mid);
for (int i=L; i<=R; i++)
{
int now=a[i].y;
int len=e[now].size();
long long sum=0;
for (int j=0; j<len; j++)sum+=query(e[now][j]);
if (sum>=a[i].x)
{

ans[now]=mid;
b[t1++]=a[i];
}
else
{
a[i].x-=sum;
b[t2--]=a[i];
} 
}
for (int i=L; i<=R; i++)a[i]=b[i];
for (int i=l; i<=mid; i++)
{
if (p[i].l<=p[i].r) add(p[i].l,-p[i].c),add(p[i].r+1,p[i].c);
else add(1,-p[i].c),add(p[i].r+1,p[i].c),add(p[i].l,-p[i].c);
}
if (t2!=R || r!=mid)solve(l,mid,L,t2);
if (t1!=L || mid+1!=l)solve(mid+1,r,t1,R);
}
int main()
{
freopen("整体二分.in","r",stdin);
freopen("整体二分.out","w",stdout);
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
memset(e,0,sizeof e);
memset(tree,0,sizeof tree);
memset(ans,0,sizeof ans);
for (int i=1; i<=m; i++)
{
int x;
scanf("%d",&x);
e[x].push_back(i);
}
for (int i=1; i<=n; i++)
{
scanf("%d",&a[i].x);
a[i].y=i; 
}
scanf("%d",&k);


for (int i=1; i<=k; i++)scanf("%d%d%d",&p[i].l,&p[i].r,&p[i].c);
solve(1,k,1,n);
for (int i=1; i<=n; i++)
{
if (ans[i]==0)printf("-1\n");
else printf("%lld\n",ans[i]);
} 
}
return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值