社区讨论

这道题树状数组套主席树的复杂度不对么?求助dalao

P1903【模板】带修莫队 / [国家集训队] 数颜色 / 维护队列参与者 3已保存回复 16

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
16 条
当前快照
1 份
快照标识符
@mi7ynrw9
此快照首次捕获于
2025/11/21 05:46
4 个月前
此快照最后确认于
2025/11/21 06:44
4 个月前
查看原帖
我开了一个set 然后T6个点一直卡set的常数 却还是40分?感觉跟题解中的思路差不多,莫非在让我写一个spaly? 求助dalao 呜呜呜~
CPP
//#include<bits/stdc++.h>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<queue>
#include<deque>
#include<vector>
#include<utility>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<ctime>
#include<map>
#include<set>
#include<bitset>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 1000000000
#define ll long long
#define l(x) t[x].l
#define r(x) t[x].r
#define v(x) t[x].v
using namespace std;
char buf[1<<15],*fs,*ft;
inline char getc()
{
	return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void put(int x)
{
	x<0?putchar('-'),x=-x:0;
	int num=0;char ch[50];
	while(x)ch[++num]=x%10+'0',x/=10;
	num==0?putchar('0'):0;
	while(num)putchar(ch[num--]);
	putchar('\n');return;
}
const int MAXN=50010;
int n,m,cnt;
int a[MAXN];
int root[MAXN],c[MAXN],w[1000010],vis[1000010],nex[1000010];
set<int>q[1000100];
set<int>::iterator tmp;
char b[2];
struct wy
{
	int l,r;
	int v;
}t[MAXN*22*22];
inline void insert(int &p,int l,int r,int x,int k)
{
	if(!p)p=++cnt;
	if(l==r){v(p)+=k;return;}
	int mid=(l+r)>>1;
	if(x<=mid)insert(l(p),l,mid,x,k);
	else insert(r(p),mid+1,r,x,k);
	v(p)=v(l(p))+v(r(p));
}
inline void add(int x,int y,int z)
{
	for(int i=x;i<=n;i+=i&(-i))insert(root[i],0,n,z,y);
}
inline int ask(int p,int l,int r,int L,int R)
{
	if(!p)return 0;
	if(L<=l&&R>=r)return v(p);
	int mid=(l+r)>>1;
	int cnt=0;
	if(L<=mid)cnt+=ask(l(p),l,mid,L,R);
	if(r>mid)cnt+=ask(r(p),mid+1,r,L,R);
	return cnt;
}
inline int ask(int L,int R)
{
	int cnt=0;
	for(int i=R;i;i-=i&(-i))cnt+=ask(root[i],0,n,0,L-1);
	for(int i=L-1;i;i-=i&(-i))cnt-=ask(root[i],0,n,0,L-1);
	return cnt;
}
int main()
{
	//freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);
	n=read();m=read();
	for(int i=1;i<=n;++i)
	{
		int flag=0;
		a[i]=read();
		q[a[i]].insert(i);
		if(!vis[a[i]])flag=1,q[a[i]].insert(0),w[a[i]]=1;
		add(i,1,flag==1?0:vis[a[i]]);
		nex[i]=vis[a[i]];vis[a[i]]=i;
	}
	for(int i=1;i<=m;++i)
	{
		int x,y,flag=0,mark=0,last;
		scanf("%s",b+1);
		x=read();y=read();
		if(b[1]=='Q')put(ask(x,y));
		else
		{
			//将其删除造成的效果
			tmp=q[a[x]].find(x);
			flag=nex[x]==0?1:0;
			if(x==vis[a[x]])mark=1;
			if(mark==0)++tmp;
			if(flag)//在队头
			{
				add(x,-1,0);
				if(!mark)
				{
					add(*tmp,-1,x);
					add(*tmp,1,0);
					nex[*tmp]=0;
				}
				else vis[a[x]]=0;
			}
			if(mark&&flag==0)//在队尾
			{
				add(x,-1,nex[x]);
				vis[a[x]]=nex[x];
			}
			if(mark==0&&flag==0)//在队中间
			{
				add(x,-1,nex[x]);
				add(*tmp,-1,x);
				add(*tmp,1,nex[x]);
				nex[*tmp]=nex[x];
			}
			q[a[x]].erase(x);//注意删除...
			//将其插入
			a[x]=y;flag=mark=0;
			if(!vis[a[x]]&&!w[a[x]])w[a[x]]=1,q[a[x]].insert(0);
			q[a[x]].insert(x);
			tmp=q[a[x]].find(x);
			last=(*(--tmp));++tmp;
			flag=last==0?1:0;
			if(vis[a[x]]<x)mark=1;
			else ++tmp;
			if(flag)//考虑在队首
			{
				add(x,1,0);nex[x]=0;
				if(!mark)
				{
					add(*tmp,-1,0);
					add(*tmp,1,x);
					nex[*tmp]=x;
				}
				else vis[a[x]]=x;
			}
			if(flag==0&&mark)//在对尾
			{
				nex[x]=vis[a[x]];
				add(x,1,nex[x]);
				vis[a[x]]=x;
			}
			if(mark==0&&flag==0)
			{
				nex[x]=last;
				add(*tmp,-1,nex[x]);
				add(x,1,nex[x]);
				add(*tmp,1,x);
				nex[*tmp]=x;
			}
		}
	}
	return 0;
}

回复

16 条回复,欢迎继续交流。

正在加载回复...