题目链接
把度数大于等于 n \sqrt n n的点归为超级点
对每个超级点x维护一个长度为d_x的数组,每个位置y,当前仅当跟x相连的z中有a_z=y时,y=1,否则为0。
修改的时候只修改跟当前点连接的超级点的信息。
有两种写法,经验证,带log和不带log的时间 都差不多。。。
查询的时候,对不是超级点的询问直接暴力跑,带log的话就是,是超级点的就在bit上二分找答案,不带log的话就是对每个超级点也分块维护每个块的sum,查询的时候遍历块找答案。
1.纯分块写法:
#include
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb emplace_back
#define mp make_pair
#define wzh(x) cerr<<#x<<' '<
int t,n,m,a[N],vis[N],num[N],d[N],bl[N],ans[N];
vector<int>v[N],mi[N],fk[N],gc[N];
struct FastIO
{
static const int S=200;
int wpos;
char wbuf[S];
FastIO():wpos(0){}
inline int xchar()
{
static char buf[S];
static int len=0,pos=0;
if(pos==len) pos=0,len=fread(buf,1,S,stdin);
if(pos==len) exit(0);
return buf[pos++];
}
inline int read()
{
int s=1,c=xchar(),x=0;
while(c<=32) c=xchar();
if(c=='-') s=-1,c=xchar();
for(;'0'<=c&&c<='9';c=xchar()) x=x*10+c-'0';
return x*s;
}
~FastIO()
{
if(wpos) fwrite(wbuf,1,wpos,stdout),wpos=0;
}
}io;
int main() {
auto rd =[&](){
return io.read();
};
for(t=rd();t;t--){
n=rd();m=rd();
int lar=0;
for(int i=1;i<=n;i++){
v[i].clear();
mi[i].clear();
d[i]=0;
}
for(int i=1;i<=n;i++)a[i]=rd();
for(int i=1;i<=m;i++){
int s,t;
s=rd();t=rd();
v[s].pb(t);
v[t].pb(s);
d[s]++;
d[t]++;
}
auto ge =[&](int x,int y){
int ans=(x+bl[y]-1)/bl[y];
return ans;
};
int lim=sqrt(n)+1;
for(int i=1;i<=n;i++){
if(d[i]>lim){
num[i]=++lar;
bl[lar]=sqrt(d[i]);
int now=(d[i]+bl[lar]-1)/bl[lar];
fk[lar].resize(now+1);
gc[lar].resize(d[i]+1);
for(int j=0;j<=d[i];j++)gc[lar][j]=0;
for(int j=0;j<=now;j++)fk[lar][j]=0;
for(auto k:v[i]){
if(d[k]>lim){
mi[i].pb(k);
}
if(a[k]<=d[i]){
if(++gc[lar][a[k]]==1){
fk[lar][ge(a[k],lar)]++;
}
}
}
}else{
for(auto k:v[i]){
if(d[k]>lim){
mi[i].pb(k);
}
}
}
}
int Q;
for(Q=rd();Q;Q--){
int ty,u,x;
ty=rd();
if(ty==1){
u=rd();x=rd();
for(auto k:mi[u]){
if(a[u]<=d[k]){
if(--gc[num[k]][a[u]]==0){
fk[num[k]][ge(a[u],num[k])]--;
}
}
if(x<=d[k]){
if(++gc[num[k]][x]==1){
fk[num[k]][ge(x,num[k])]++;
}
}
}
a[u]=x;
}else{
u=rd();
if(d[u]<=lim){
for(int i=0;i<=d[u];i++)ans[i]=0;
for(auto k:v[u])ans[a[k]]=1;
for(int i=0;i<=d[u];i++){
if(!ans[i]){
printf("%d\n",i);
break;
}
}
}else{
if(!gc[num[u]][0]){
puts("0");
continue;
}
int sum=bl[num[u]];
int tmp=(d[u]+sum-1)/sum;
for(int i=1;i<=tmp;i++){
int res=min(d[u],i*sum)-(i-1)*sum;
if(fk[num[u]][i]<res){
for(int j=(i-1)*sum+1;j<=min(d[u],i*sum);j++){
if(!gc[num[u]][j]){
printf("%d\n",j);
break;
}
}
break;
}
}
}
}
}
}
return 0;
}
2.bit写法:
#include
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb emplace_back
#define mp make_pair
#define wzh(x) cerr<<#x<<' '<
int t, n, m, a[N], d[N], pre[N];
vector<int>v[N], me[N];
vector<int>mi[N];
set<int>s[N];
int vis[N];
multiset<int>q[N];
struct FastIO {
static const int S = 200;
int wpos;
char wbuf[S];
FastIO(): wpos(0) {}
inline int xchar(){
static char buf[S];
static int len = 0, pos = 0;
if (pos == len) pos = 0, len = fread(buf, 1, S, stdin);
if (pos == len) exit(0);
return buf[pos++];
}
inline int read() {
int s = 1, c = xchar(), x = 0;
while (c <= 32) c = xchar();
if (c == '-') s = -1, c = xchar();
for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
return x * s;
}
~FastIO()
{
if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
}
} io;
vector<int>fk[444], gc[444];
int szz[N];
void add(int x, int y, int z) {
int sz = szz[x];
for (; y <= sz; y += y & -y)gc[x][y] += z;
}
int get(int x, int y) {
int sz = 0;
for (; y; y -= y & -y)sz += gc[x][y];
return sz;
}
int num[N];
int main() {
t = io.read();
for (; t; t--) {
n = io.read(); m = io.read();
int lar = 0;
for (int i = 1; i <= n; i++) {
v[i].clear();
a[i] = io.read();
d[i] = 0;
mi[i].clear();
}
for (int i = 1; i <= m; i++) {
int s, t;
s = io.read(); t = io.read();
v[s].pb(t);
v[t].pb(s);
d[s]++; d[t]++;
}
int lim = sqrt(n) ;
for (int i = 1; i <= n; i++) {
if (d[i] >= lim) {
num[i] = ++lar;
szz[lar]=d[i];
fk[lar].resize(d[i] + 2);
gc[lar].resize(d[i] + 2);
for (int j = 0; j <= d[i]; j++)fk[lar][j] = gc[lar][j] = 0;
for (auto k : v[i]) {
if (a[k] <= d[i]) {
fk[lar][a[k]]++;
if (a[k]) {
if(fk[lar][a[k]]==1)add(lar, a[k], 1);
}
}
}
}
}
for (int i = 1; i <= n; i++) {
for (auto k : v[i]) {
if (d[k] >= lim) {
mi[i].pb(k);
}
}
}
int Q;
Q = io.read();
for (; Q; Q--) {
int ty, u, x;
ty = io.read();
if (ty == 1) {
u = io.read();
x = io.read();
if (a[u] == x)continue;
for (auto pac : mi[u]) {
int nu = num[pac];
if (a[u] <= d[pac]) {
fk[nu][a[u]]--;
if (fk[nu][a[u]] == 0 && a[u]) {
add(nu, a[u], -1);
}
}
if (x <= d[pac]) {
fk[nu][x]++;
if (fk[nu][x] == 1 && x) {
add(nu, x, 1);
}
}
}
a[u] = x;
} else {
u = io.read();
if (d[u] >= lim) {
int nu = num[u];
if (!fk[nu][0])puts("0");
else {
int l = 1, r = d[u], ans = -1;
while (l <= r) {
int mid = l + r >> 1;
if (get(nu, mid) < mid)ans = mid, r = mid - 1;
else l = mid + 1;
}
assert(ans != -1);
printf("%d\n", ans);
}
}
else {
for (int i = 0; i <= d[u]; i++)vis[i] = 0;
for (auto k : v[u]) {
if (a[k] <= d[u])vis[a[k]] = 1;
}
for (int i = 0; i <= d[u]; i++) {
if (!vis[i]) {
printf("%d\n", i);
break;
}
}
}
}
}
for (int i = 1; i <= lar; i++)gc[i].clear(), fk[i].clear();
}
return 0;
}