背景:
最近
CSDN bug
\text{CSDN bug}
CSDN bug好多。
难道这启示我用博客园备份?
今晚就是用来补博客的坑的。
题目传送门:
https://www.luogu.org/problem/P3527
题意:
给出两个序列
A
,
b
A,b
A,b,其中
b
i
b_i
bi表示
b
b
b序列中下标为
i
i
i的对应的是
a
a
a中下标的
b
i
b_i
bi,
A
i
A_i
Ai表示
a
a
a的目标状态。
其实
b
b
b围成了一个环。
有点绕。
然后有区间加操作,有按照顺序的时刻,每一次在
b
b
b中区间
x
x
x到
y
y
y之间加上
z
z
z,看作对
b
b
b对应的
a
a
a加
z
z
z。
对于每一个
i
i
i,询问
a
a
a中第
i
i
i个元素什么时刻达到目标状态
A
i
A_i
Ai。
自己意会吧。
思路:
考虑整体二分。
二分答案(时刻)。
你发现询问操作只用最后统计出每一个
b
b
b对应的
a
a
a中位置的值一次,然后看看是否达到目标。可以用
vector
\text{vector}
vector确定这种对应关系,将
b
b
b映射到
a
a
a上,最后查询即可,容易发现,这样均摊时间复杂度:
Θ
(
m
)
\Theta(m)
Θ(m)。
修改操作用差分树状数组(当然你可以用线段树)维护,在
b
b
b中加,将区间断环成链,暴力加即可。
因此时间复杂度:
Θ
(
m
log
m
log
q
)
\Theta(m\log m\log q)
Θ(mlogmlogq)(
q
q
q为时刻数)。
代码:
听了 brz \text{brz} brz的建议将询问和修改操作用两个东西。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define lowbit(x) ((x)&(-(x)))
#define LL long long
using namespace std;
vector<int> F[300010];
int n,m,q;
LL tot[3000010],tr[300010];
int a[300010],d1[300010],d2[300010],ans[300010];
struct node{int x,y,z;} b[300010];
void Add(int x,int y)
{
for(;x<=m;x+=lowbit(x))
tr[x]+=y;
}
void add(int x,int y,int z)
{
if(x<=y) Add(x,z),Add(y+1,-z); else Add(1,z),Add(y+1,-z),Add(x,z),Add(m+1,-z);
}
LL getsum(int x)
{
LL tot=0;
for(;x;x-=lowbit(x))
tot+=tr[x];
return tot;
}
void dfs(int l,int r,int L,int R)
{
if(l==r)
{
for(int i=L;i<=R;i++)
ans[a[i]]=l;
return;
}
int mid=(l+r)>>1,t1=0,t2=0;
for(int i=l;i<=mid;i++)
add(b[i].x,b[i].y,b[i].z);
for(int i=L;i<=R;i++)
{
LL sum=0;
bool flag=false;
for(int j=0;j<F[a[i]].size();j++)
{
sum+=getsum(F[a[i]][j]);
if(sum>=tot[a[i]]) {flag=true,d1[++t1]=a[i];break;}
}
if(!flag) tot[a[i]]-=sum,d2[++t2]=a[i];
}
for(int i=l;i<=mid;i++)
add(b[i].x,b[i].y,-b[i].z);
for(int i=1;i<=t1;i++)
a[L+i-1]=d1[i];
for(int i=1;i<=t2;i++)
a[L+t1+i-1]=d2[i];
dfs(l,mid,L,L+t1-1);
dfs(mid+1,r,L+t1-1+1,R);
}
int main()
{
int x,y,z;
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&x);
F[x].push_back(i);
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&tot[i]);
a[i]=i;
}
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%d %d %d",&x,&y,&z);
b[i]=(node){x,y,z};
}
dfs(1,q+1,1,n);
for(int i=1;i<=n;i++)
if(ans[i]<=q) printf("%d\n",ans[i]); else printf("NIE\n");
}