社区讨论
这道题树状数组套主席树的复杂度不对么?求助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 条回复,欢迎继续交流。
正在加载回复...