玄学莫队TLE on #21 求助
查看原帖
玄学莫队TLE on #21 求助
220824
yyz1005楼主2023/5/20 16:17

可能莫队真的不适合我 :(

用 tot[] 记录每个颜色出现的次数

用树状数组记录出现指定次数的颜色的个数

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll GetLL(){
	ll x = 0,h = 1;
	char ch = getchar();
	while(!(ch=='-'||('0'<=ch&&ch<='9'))) ch = getchar();
	if(ch=='-') h = -1;
	else x = ch-'0';
	ch = getchar();
	while('0'<=ch&&ch<='9'){
		x = x*10+ch-'0';
		ch = getchar();
	}
	return x*h;
}
const ll N = 100010;
ll n,Q;
vector<ll> vec[N];
ll anc[N][40];
ll dep[N];
vector<ll> rt;
ll siz[N],son[N];
void dfs1(ll id,ll fa){
	anc[id][0] = fa;
	siz[id]++;
	ll mx = 0;
	for(ll j = 1; j <= 30; j++) anc[id][j] = anc[anc[id][j-1]][j-1];
	for(auto v : vec[id]){
		if(v==fa) continue;
		dep[v] = dep[id]+1;
		dfs1(v,id);
		if(siz[v]>mx) mx = siz[v],son[id] = v;
		siz[id]+=siz[v];
	}
}
ll req[N],num = 0,ls[N],rs[N];//id's son : (ls[id],rs[id])
ll name[N];
void ReDfs(ll id,ll fa){
	num++,req[num] = id;
	ls[id] = num;
	if(son[id]) ReDfs(son[id],id);
	for(auto v : vec[id]){
		if(v==fa||v==son[id]) continue;
		ReDfs(v,id);
	}
	rs[id] = num;
}
ll AskFather(ll id,ll k){
	for(ll j = 30; j >= 0; j--){
		if(k&(1<<j)){
			id = anc[id][j];
			k-=(1<<j);
		}
	}
	return id;
}

//莫队 

ll BelSize;
#define bel(x) (x/BelSize) 
struct question{
    ll id;
    ll ql;
    ll qr;
    ll val;
    bool operator <(const question &b) const{
        return bel(ql)==bel(b.ql)?qr<b.qr:bel(ql)<bel(b.ql);
    }
} q[N];
ll qtot = 0;
ll ans[N];
ll tot[N];
#define lowbit(x) (x&-x);
ll st[N],maxn = 100000;
void Stadd(ll id,ll x){
	id++;
	while(id<=maxn){
		//printf("%lld\n",id);
		st[id]+=x;
		id+=lowbit(id);
	}
}
ll Stsum(ll id){
	id++;
	ll ret = 0;
	while(id>0){
		//printf("%lld-%lld\n",id,st[id]);
		ret+=st[id];
		id-=lowbit(id);
	}
	return ret;
}
void add(ll id){
	//printf("pos = %lld --\n",tot[name[req[id]]]);
	Stadd(tot[name[req[id]]],-1);
	tot[name[req[id]]]++;
	//printf("pos = %lld ++\n",tot[name[req[id]]]);
	Stadd(tot[name[req[id]]],1);
}
void del(ll id){
	//printf("pos = %lld --\n",tot[name[req[id]]]);
	Stadd(tot[name[req[id]]],-1);
	tot[name[req[id]]]--;
	//printf("pos = %lld ++\n",tot[name[req[id]]]);
	Stadd(tot[name[req[id]]],1);
}
void Solve(){
	sort(q+1,q+qtot+1);
	//dep[req]
	for(ll i = 1,l = 1,r = 0; i <= qtot; i++){
		if(q[i].ql==-1){
			ans[q[i].id] = 0;
			continue;
		}
		//printf("----------\nQuestion %lld:%lld-%lld k = %lld\n",q[i].id,q[i].ql,q[i].qr,q[i].val);
        while (l > q[i].ql) add(--l);
        while (r < q[i].qr) add(++r);
        while (l < q[i].ql) del(l++);
        while (r > q[i].qr) del(r--);
        //printf("This Question's answer = %lld-%lld = %lld\n",Stsum(8),Stsum(ans[q[i].val]-1),Stsum(8)-Stsum(q[i].val-1));
        ans[q[i].id] = Stsum(maxn)-Stsum(q[i].val-1);
        
    }
    for(ll i = 1; i <= qtot; i++) printf("%lld\n",ans[i]);
}

//莫队 
string ScanStr(){
	string res = "";
	char ch = getchar();
	while(!('a'<=ch&&ch<='z')) ch = getchar();
	res+=ch;
	ch = getchar();
	while('a'<=ch&&ch<='z'){
		res+=ch;
		ch = getchar();
	} 
	return res;
}
int main(){
	n = GetLL();
	Q = GetLL();
	BelSize = sqrt(n);
	for(ll i = 1; i <= n; i++) name[i] = GetLL();
	for(ll i = 1; i < n; i++){
		ll x = GetLL(),y  = GetLL();
		vec[x].push_back(y);
		vec[y].push_back(x);
	}
		dep[1] = 0;
		dfs1(1,0);
		ReDfs(1,0);
	while(Q--){
		ll id = GetLL(),k = GetLL();
		/*
		if(k>dep[id]){
			qtot++;
			q[qtot].id = qtot;
			q[qtot].ql = -1;
			q[qtot].qr = 0;
			q[qtot].val = 0;
			continue;
		}
		*/
		//id = AskFather(id,k);
		//id 的 k 级 son 
		//printf("%lld\n",id);
		qtot++;
		q[qtot].id = qtot;
		q[qtot].ql = ls[id];
		q[qtot].qr = rs[id];
		q[qtot].val = k;
	}
	Solve();
	return 0;
}
2023/5/20 16:17
加载中...