灯
灯

题解
话说这道题暴力都能过
应该是很容易想到分块的。
当我们将一个点翻转时,它所产生的贡献为
该
颜
色
中
前
面
灯
没
亮
的
灯
−
后
面
灯
亮
着
的
灯
该颜色中前面灯没亮的灯-后面灯亮着的灯
该颜色中前面灯没亮的灯−后面灯亮着的灯。这应该是很容易理解的,段数可以看成有多少个点前面关后面开,我们只需要知道它的改变量。
考虑这东西这么维护,如果直接暴力的话明显会T掉其实卡卡是能过的,考虑分块。
我们将出现次数小于
n
\sqrt{n}
n的点每次直接暴力修改统计,大于
n
\sqrt{n}
n的点在修改其它点的过程中将以上两个量的变化记录下来。
对于大于
n
\sqrt{n}
n的点的修改时对于其它大于
n
\sqrt{n}
n对点的贡献可以先预处理出这些点相邻的个数,在直接对整体修改。
这样就可以使每次修改的时间复杂度降至
O
n
O\sqrt{n}
On。
总时间复杂度 O ( n n ) O(n\sqrt{n}) O(nn)。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define MAXN 100005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
typedef unsigned int uint;
typedef pair<int,int> pii;
const int INF=0x7f7f7f7f;
const int mo=1e9+7;
const int n1=300;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
int n,m,q,a[MAXN],ans,id[MAXN],tim[MAXN];
int num[405][405],cnt1[MAXN],cnt2[MAXN],ord[MAXN],idx;
bool col[MAXN],vis[MAXN];vector<int>W[MAXN];
signed main(){
freopen("light.in","r",stdin);
freopen("light.out","w",stdout);
read(n);read(m);read(q);for(int i=1;i<=n;i++)read(a[i]),W[a[i]].push_back(i),tim[a[i]]++;
for(int i=1;i<=m;i++)if(tim[i]>n1)id[i]=++idx,ord[idx]=i;
for(int i=1;i<=n;i++)if(a[i]^a[i-1])cnt1[a[i]]++,num[id[a[i-1]]][id[a[i]]]++;
for(int i=1;i<=q;i++){
int x,siz;read(x);col[x]^=1;
if(col[x]){
if(tim[x]<n1)
for(int j=0;j<W[x].size();j++){
if(a[W[x][j]-1]^a[W[x][j]])ans+=(!col[a[W[x][j]-1]]),cnt2[a[W[x][j]-1]]++;
if(a[W[x][j]+1]^a[W[x][j]])ans-=col[a[W[x][j]+1]],cnt1[a[W[x][j]+1]]--;
}
else{
ans+=cnt1[x]-cnt2[x];
for(int j=0;j<=idx;j++)
cnt2[ord[j]]+=num[j][id[x]],cnt1[ord[j]]-=num[id[x]][j];
}
}
else{
if(tim[x]<n1)
for(int j=0;j<W[x].size();j++){
if(a[W[x][j]-1]^a[W[x][j]])ans-=(!col[a[W[x][j]-1]]),cnt2[a[W[x][j]-1]]--;
if(a[W[x][j]+1]^a[W[x][j]])ans+=col[a[W[x][j]+1]],cnt1[a[W[x][j]+1]]++;
}
else{
ans+=cnt2[x]-cnt1[x];
for(int j=0;j<=idx;j++)
cnt2[ord[j]]-=num[j][id[x]],cnt1[ord[j]]+=num[id[x]][j];
}
}
printf("%d\n",ans);
}
return 0;
}

浙公网安备 33010602011771号