分块大法吼啊!(ಡωಡ)
虽然知道是线段树。
但是我觉得好久没搞线段树。我不会打惹过于无趣。
所以用了分块。
谁叫这题数据<=,明摆着练分块的,分块的每次操作是
然后就是经常有的:码字15分钟,debug 2小时,搞得我连模拟题都没做完。
。。。难受qwq
分块思想
把一个整体分成一块块,遍历块比遍历点快很多很多很多。。
不知道数据是不是随机的,所以把整体分成块,因为这样理论上是最快的,请自行了解~~
本题思路
首先是基本要有的
1.:代表一个块有
个元素
2.:代表有
个块
就是这个没处理好,害的我白提交6次,多耗费1h多时间
3.:代表第i个块里有
个元素
4.:代表第i个元素在第
个块里
接下来是本题的操作
5.题目思想:先打一个最开始的,照抄
里面的就行,然后我们想,每把第
个从
变成
,就会增加
到其他点距离和的值(
),反之,则减少
点到其他点距离和的值(
)。
6.:代表第
个块里所有点到该块左边界(
)的距离
7.:代表第
个块里所有点到该块右边界(
)的距离
本题核心qwq
那么每次新来一个,不管是加还是减,都要先求出距离和,所以如何求距离和呢?
不妨画一个图,有点丑。。。。
红色的是修改的点
假设这个图就这么点东西:
1.两条就是
2.对于该块外的点,增加的距离和是
一.左侧:,加1是细节问题,
是中间完整块的长度
二.右侧:
3.对于块内的点,直接枚举反正一个块也就
4.注意,对于修改完的红点,需要在原来的地方进行,并且同时维护那几个数组
然后就没了~~
贴上蒟蒻代码:
#include<bits/stdc++.h>
#define maxn 100010
#define Mod 1000000007
using namespace std;
int n,m,last;
long long num,sum,now,block;
string str;
bool Map[maxn];
int bll[1010],blr[1010],blv[1010],seat[maxn],blnum;
void Build()
{
block=sqrt(n);
if(n%block!=0) ++block;
if(n%block==0) blnum=n/block;
else blnum=n/block+1;
for(int i=1;i<=n;++i)
seat[i]=(i-1)/block+1;
for(int i=1;i<=n;++i){
int j=str[i-1];
if(j=='0') continue;
++blv[seat[i]];
bll[seat[i]]+=i-(block*(seat[i]-1)+1);
blr[seat[i]]+=min(block*seat[i],1LL*n)-i;
}
}
long long Dis_sum(int x){
long long res=0;
long long x_l=x-(1LL*(seat[x]-1)*block+1),x_r=min(1LL*seat[x]*block,1LL*n)-x;
if(seat[x]>1)
for(int i=seat[x]-1;i>=1;--i){
long long m_dis=1LL*(seat[x]-i-1)*block;
res=(res+(x_l+m_dis+1)*blv[i]%Mod+blr[i])%Mod;
}
if(seat[x]<blnum)
for(int i=seat[x]+1;i<=blnum;++i){
long long m_dis=1LL*(i-seat[x]-1)*block;
res=(res+(x_r+m_dis+1)*blv[i]%Mod+bll[i])%Mod;
}
for(int i=(seat[x]-1)*block+1;i<=min(seat[x]*block,1LL*n);++i)
if(Map[i]==1)
res=(res+1LL*abs(i-x))%Mod;
return res;
}
int main(){
scanf("%d",&n);
cin>>str;
Build();
for(int i=0;i<n;++i){
if(str[i]=='1'){
now=(now+(i-last)*num%Mod)%Mod;
sum=(sum+now)%Mod;
last=i;
num++;
Map[i+1]=1;
}
else Map[i+1]=0;
}
printf("%lld\n",sum);
scanf("%d",&m);
for(int i=1;i<=m;++i){
int opt,x;
scanf("%d%d",&opt,&x);
long long dis_sum=Dis_sum(x);
if(opt==1){
Map[x]=1;
blv[seat[x]]++;
bll[seat[x]]+=x-((seat[x]-1)*block+1);
blr[seat[x]]+=min(1LL*n,seat[x]*block)-x;
sum=(sum+dis_sum)%Mod;
printf("%lld\n",sum);
}
if(opt==2){
Map[x]=0;
blv[seat[x]]--;
bll[seat[x]]-=x-((seat[x]-1)*block+1);
blr[seat[x]]-=min(seat[x]*block,1LL*n)-x;
sum=(sum-dis_sum+1LL*100000*Mod)%Mod;
printf("%lld\n",sum);
}
}
return 0;
}
分块永远是正宫...这种思想啥都能维护(ಡωಡ)

京公网安备 11010502036488号