2025-10-22 ZR-J 模拟赛 赛后总结【ZR】

光速打完前三题,然后被 T4 击败。

结果挂完了。

50+10+100+0。

T1 Letters

题意

给定 \(n\) 个单词,对于这些单词组成的集合的所有子集,问这些子集中 az 26 个字母均出现过至少一次的子集总数。

赛时

经过 0 秒的思考糊上去个 bitset\(O(\frac{n2^n}{w})\) 做法。结果复杂度少算个 \(n\) 挂成 50pts。

题解

我觉得不需要写什么题解了。暴力跑 dfs 复杂度比我 bitset 低。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3fll
using namespace std;

int n;
int a[26];
long long ans=0;

void dfs(int x,int nw=0){
    if(x==n+1) ans+=(nw==(1<<26)-1);
    else{
        dfs(x+1,nw);
        dfs(x+1,nw|a[x]);
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);

    cin>>n;
    for(int i=1;i<=n;i++){
        string s;cin>>s;
        for(char c:s) a[i]|=(1<<(c-'a'));
    }
    dfs(1,0);
    cout<<ans;

    return 0;
}

T2 Circle

题意

平面上有 \(n\) 个圆,圆心为 \((x_i,0)\),半径为 \(r_i\)

圆之间只会相切,不会相交。

问这些圆把平面分成多少部分。

赛时

严厉批判 ZR 不给大洋里。

结果挂成 10pts。差点没给我 rating 干开线。

题解

把圆转化成数轴上的线段,那么每个圆的贡献为 \(1\) 当且仅当这条线段所在的所有位置均被其他线段所覆盖。

所以把线段按长度排序,然后上个线段树就解决了。

或者用个别的神秘数据结构比如珂朵莉树。

抄了 mhh 的思路。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3fll
using namespace std;

int n;
struct node{
    int l,r;
    bool operator<(const node&_Q)const{return r-l+1<_Q.r-_Q.l+1;}
    bool operator==(const node&_Q)const{return l==_Q.l&&r==_Q.r;}
}a[300010];

vector<int> vec;
map<int,int> mp;int unq;

int fa[600010];

struct node2{
    int l,r,v,lz;
}t[2400010];

void pushdown(int p){
    if(t[p].lz){
        t[p<<1].v=1;
        t[p<<1].lz=1;
        t[p<<1|1].v=1;
        t[p<<1|1].lz=1;
    }
}
void pushup(int p){
    t[p].v=t[p<<1].v&t[p<<1|1].v;
}

void build(int l,int r,int p=1){
    t[p]={l,r,0,0};
    if(l==r) return;
    int mid=(l+r)>>1;
    build(l,mid,p<<1);
    build(mid+1,r,p<<1|1);
    pushup(p);
}

void change(int l,int r,int p=1){
    if(l<=t[p].l&&t[p].r<=r){
        t[p].v=1;
        t[p].lz=1;
    }else{
        if(t[p].lz) return;
        pushdown(p);
        int mid=(t[p].l+t[p].r)>>1;
        if(l<=mid) change(l,r,p<<1);
        if(r>mid) change(l,r,p<<1|1);
        pushup(p);
    }
}

int query(int l,int r,int p=1){
    if(l<=t[p].l&&t[p].r<=r) return t[p].v;
    if(t[p].lz) return 1;
    pushdown(p);
    int res=1;
    int mid=(t[p].l+t[p].r)>>1;
    if(l<=mid) res&=query(l,r,p<<1);
    if(r>mid) res&=query(l,r,p<<1|1);
    return res;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);

    cin>>n;
    for(int i=1;i<=n;i++){
        int x,r;cin>>x>>r;
        a[i]={x-r,x+r};
    }


    for(int i=1;i<=n;i++) vec.push_back(a[i].l);
    for(int i=1;i<=n;i++) vec.push_back(a[i].r);
    sort(vec.begin(),vec.end());
    mp[vec[0]]=++unq;
    for(int i=1;i<vec.size();i++) if(vec[i]!=vec[i-1]) mp[vec[i]]=++unq;
    for(int i=1;i<=n;i++) a[i].l=mp[a[i].l];
    for(int i=1;i<=n;i++) a[i].r=mp[a[i].r]-1;


    build(1,unq);
    int ans=1;
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        if(a[i]==a[i-1]) continue;
        if(a[i].l>a[i].r) continue;
        ans+=query(a[i].l,a[i].r)+1;
        change(a[i].l,a[i].r);
    }
    cout<<ans;

    return 0;
}

T3 Bag

题意

\(n\) 个物品和 \(m\) 个背包。物品有 \(w_i\) 的价值和 \(c_i\) 的重量。

每个背包只能装一个重量不大于 \(v_i\) 的物品。

最大化价值总和。

题解

显然贪心。

双指针带个堆就够了。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3fll
using namespace std;

int n,k;
struct node{
    long long w,c;
    bool operator<(const node&_Q)const{return c<_Q.c;}
}a[300010];
long long v[300010];

vector<int> vec;
map<long long,int> mp;int unq;

priority_queue<long long> q;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);

    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i].c>>a[i].w;
    for(int i=1;i<=k;i++) cin>>v[i];
    sort(v+1,v+1+k);
    sort(a+1,a+1+n);

    int p=1;
    long long ans=0;
    for(int i=1;i<=k;i++){
        while(p<=n&&a[p].c<=v[i]) q.push(a[p].w),p++;
        if(!q.empty()) ans+=q.top(),q.pop();
    }
    cout<<ans;

    return 0;
}

总结

挂完了。

严厉谴责 ZR 不给大洋里。

posted @ 2025-10-23 19:21  AeeE5x  阅读(4)  评论(0)    收藏  举报