第一次专题考试总结

通过率

T1:赛时总 \(92\) 提交,通过 \(49\),通过率 \(53.26\%\)
T2:赛时总 \(62\) 提交,通过 \(21\),通过率 \(33.87\%\)
T3:赛时总 \(39\) 提交,通过 \(7\),通过率 \(17.94\%\)
T4:赛时共 \(58\) 提交,通过 \(9\),通过率 \(15.55\%\)

基于通过率,认定 橙黄绿蓝,同时出题人的题目难度分配还是比较合理的qwq。

T1

\(16min\) done。
完完全全的板子题,各种方法都可以过,这里我选择了离散化后前缀和,AC 嘞。

#include<bits/stdc++.h>
#define int long long
using namespace std;
static int sum[2000005],x[200005],y[200005];
signed main(){
    cin.tie(nullptr)->ios::sync_with_stdio(0);
    int n;cin>>n;
    vector<int>v;
    for (int i=1;i<=n;++i)cin>>x[i];
    for (int i=1;i<=n;++i)cin>>y[i];
    for (int i=1;i<=n;++i)v.push_back(x[i]);
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    int m=v.size();
    for (int i=1;i<=n;++i){
        int pos=lower_bound(v.begin(),v.end(),x[i])-v.begin()+1;
        sum[pos]+=y[i];
    }
    for (int i=1;i<=m;++i)sum[i]+=sum[i-1];
    int q;cin>>q;
    for (int i=1;i<=q;++i){
        int l,r;cin>>l>>r;
        int L=lower_bound(v.begin(),v.end(),l)-v.begin()+1;
        int R=upper_bound(v.begin(),v.end(),r)-v.begin();
        if(L>R)cout<<0<<'\n';
        else cout<<sum[R]-sum[L-1]<<'\n';
    }
}

T2

DSU on tree 板子。然后就没了。

#include <bits/stdc++.h>
using namespace std;
const int N=50005;
int n,c[N],cc[N];
struct xys{
    int v,id;
}a[N];
int hd[N],to[N*2],nxt[N*2],tott;
int sz[N],son[N],tin[N],t[N],s[N],tot;
int cnt[N],sum,ans[N];
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while (!isdigit(ch)){
		if (ch=='-') 
			f=-1;
		ch=getchar();
	}
	while (isdigit(ch)){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
inline void write(int x){
	if (x<0)putchar('-'),x=-x;
	if (x>9)write(x/10);
	putchar(x%10+'0');
}
bool cmp(xys x,xys y){
    return x.v<y.v;
}
void add(int u,int v){
    to[++tott]=v;
    nxt[tott]=hd[u];
    hd[u]=tott;
}
void dfs1(int u,int fa){
    sz[u]=1;son[u]=0;
    tin[u]=++tot;s[tot]=u;
    for(int i=hd[u];i;i=nxt[i]){
        int v=to[i];if(v==fa)continue;
        dfs1(v,u);
        sz[u]+=sz[v];
        if(sz[v]>sz[son[u]])son[u]=v;
    }
    t[u]=tot;
}
static void modify(int x){
    cnt[cc[x]]++;
    if(cnt[cc[x]]&1)sum++;
    else sum--;
}
static void del(int x){
    cnt[cc[x]]--;
    if(cnt[cc[x]]&1)sum++;
    else sum--;
}
void dfs2(int u,int fa,int ok){
    for(int i=hd[u];i;i=nxt[i]){
        int v=to[i];if(v==fa||v==son[u])continue;
        dfs2(v,u,0);
    }
    if(son[u])dfs2(son[u],u,1);
    for(int i=hd[u];i;i=nxt[i]){
        int v=to[i];if(v==fa||v==son[u])continue;
        for(int j=tin[v];j<=t[v];j++)modify(s[j]);
    }
    modify(u);
    ans[u]=sum;
    if(!ok){
        for(int j=tin[u];j<=t[u];j++)del(s[j]);
    }
}
int main(){
    n=read();
    for(int i=1;i<=n;i++){c[i]=read();a[i].v=c[i];a[i].id=i;}
    sort(a+1,a+n+1,cmp);
    int m=0;
    for(int i=1;i<=n;i++){
        if(i==1||a[i].v!=a[i-1].v)m++;
        cc[a[i].id]=m;
    }
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        add(u,v);add(v,u);
    }
    dfs1(1,0);
    dfs2(1,0,1);
    for(int i=1;i<=n;i++)write(ans[i]),putchar('\n');
    return 0;
}

但是,这还是太超纲了,我们需要一个 bitset 做法。

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+5;
bitset<N>b[N];
int c[N];
struct edge{
    int to,nxt;
}e[N*2];
int hd[N],tot;
void add(int u,int v){
    e[++tot].to=v;
    e[tot].nxt=hd[u];
    hd[u]=tot;
}
int ans[N];
void dfs(int u,int fa){
    for (int i=hd[u];i;i=e[i].nxt){
        int v=e[i].to;
        if (v==fa)continue;
        dfs(v,u);
        b[u]^=b[v];
    }
    b[u].flip(c[u]);
    ans[u]=b[u].count();
}
int main(){
    int n;cin>>n;
    vector<int>v;
    for (int i=1;i<=n;++i){cin>>c[i];v.push_back(c[i]);}
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    for (int i=1;i<=n;++i)c[i]=lower_bound(v.begin(),v.end(),c[i])-v.begin()+1;
    for (int i=1;i<n;++i){
        int x,y;cin>>x>>y;
        add(x,y);add(y,x);
    }
    dfs(1,0);
    for (int i=1;i<=n;++i)cout<<ans[i]<<'\n';
}

需要注意的是,不能写 b[u]=b[u]^b[v],要写 b[u]^=b[v] 以免空间炸掉。

T3

板子题,需要维护所有长度为 \(k\) 区间的第 \(r\) 大,比较浅显的一个想法是带删对顶堆,然后代码太多了,更浅显的一个想法是线段树二分,代码比第一个稍微少一点但还要写离散化很烦人,最后我写了 BIT 二分,当然平衡树什么的维护也可以的qwq。

T4

无趣题。考虑每次都除二除二的太慢了,我们预处理出每个数除二的个数,放到直角坐标系上去表示,发现就是二维数点,离线扫描线即可。

posted @ 2026-02-15 08:43  Cefgskol  阅读(1)  评论(0)    收藏  举报