在这里插入图片描述

题解

话说这道题暴力都能过

应该是很容易想到分块的。
当我们将一个点翻转时,它所产生的贡献为 该 颜 色 中 前 面 灯 没 亮 的 灯 − 后 面 灯 亮 着 的 灯 该颜色中前面灯没亮的灯-后面灯亮着的灯 。这应该是很容易理解的,段数可以看成有多少个点前面关后面开,我们只需要知道它的改变量。
考虑这东西这么维护,如果直接暴力的话明显会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;
}


谢谢!!!

posted @ 2021-04-04 17:32  StaroForgin  阅读(10)  评论(0)    收藏  举报  来源