YL 模拟赛总结 6

Posted on 2024-03-02 17:17  _XOFqwq  阅读(5)  评论(0编辑  收藏  举报

Problem


T1

为了方便处理,我们令男生为 \(1\),女生为 \(-1\)

求一遍前缀和 \(sum\),若存在两个下标 \(l,r\) 使得 \(sum_l=sum_r\),则说明区间 \([l+1,r]\) 的和为 \(0\),即男女人数相等。在这样的区间中取长度最大的即可。

需要特殊处理 \(sum_0\)

#include<bits/stdc++.h>
#define int long long
using namespace std;

int n,ans=-1e9;
int a[100031],s[100031];
map<int,bool> vis;
map<int,int> first;

signed main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(!a[i]) a[i]=-1;
        s[i]=s[i-1]+a[i];
        //cout<<s[i]<<' ';
    }
    //cout<<'\n';
    vis[s[0]]=1; //特殊处理sum_0
    for(int i=1;i<=n;i++){
        if(!vis[s[i]]) vis[s[i]]=1,first[s[i]]=i;
        else{
            if(ans<i-first[s[i]]){
                ans=i-first[s[i]];
                //cout<<last[s[i]]+1<<' '<<i<<'\n';
            }
        }
    }
    cout<<(ans==-1e9?0:ans);
    return 0;
}

T2

将字符串 \(A\) 按照下标 \(\bmod \gcd(|A|,|B|)\) 的值进行分类,统计 \(A\) 中每一类中的每一个字符在字符串 \(B\) 中出现的次数,将这些次数相加即为每一类字符的匹配次数,乘以 \(\dfrac{n}{\operatorname{lcm}(|A|,|B|)}\)(即以 \(\operatorname{lcm}(|A|,|B|)\) 为循环节的循环次数)即为答案。

#include<bits/stdc++.h>
#define int long long
using namespace std;

int n,m,ans,x;
string s,t;
int cnt[31][1000031];

signed main(){
    cin>>n>>m>>s>>t;
    x=__gcd(s.size(),t.size());
    for(int i=0;i<t.size();i++)
        cnt[i%x][t[i]-'a'+1]++;
    for(int i=0;i<s.size();i++)
        ans+=cnt[i%x][s[i]-'a'+1];
    cout<<ans*(n/(s.size()/x*t.size()/s.size()));
    return 0;
}

T3

我们令节点 \(x\) 需要染黑的点的总数为 \(all\)

首先题目中所说的 \(B\) 限制其实可以转化为“至少要将节点 \(x\) 的子树内至少要有 \(all-y\) 个点被染黑。

同时 \(A\) 限制中若多次出现同一个 \(x\),则仅需保留最大值。

然后就进行一遍树形 dp,求出树上每个节点的子树大小,并将节点 \(x\) 子树中所有需要染黑的点都算到 \(x\) 下面。

接着我们发现经过转化后的 \(B\) 限制中需要染黑的节点数其实已经包括了子树内需要染黑的节点数,也就是说 \(B\) 限制中需要染黑的节点数一定 \(\ge A\) 限制中需要染黑的节点数。

于是我们又发现,因为子树大小不变,所以 \(all\) 越大就越可能满足上述条件。

因此我们考虑二分 \(all\) 的值,检验其是否满足条件即可。

#include<bits/stdc++.h>
using namespace std;

int n,a,b;
vector<int> e[100031];
int ax[100031],bx[100031];
int ain[100031],fin[100031];
int sz[100031];

void dfs(int u,int fa){
    int sum=0;
    sz[u]=1;
    for(auto i:e[u])
        if(i!=fa) dfs(i,u),sz[u]+=sz[i],sum+=ain[i];
    ain[u]=max(ain[u],sum);
}
bool judge(int u,int fa){
    int sum=1;
    for(auto i:e[u]){
        if(i!=fa){
            if(!judge(i,u)) return 0;
            sum+=fin[i];
        }
    }
    fin[u]=min(fin[u],sum);
    return fin[u]>=ain[u];
}
bool check(int x){
    for(int i=1;i<=n;i++) fin[i]=sz[i];
    for(int i=1;i<=b;i++) fin[ax[i]]=min(fin[ax[i]],x-bx[i]);
    return judge(1,0)&&fin[1]>=x;
}

int main(){
    cin>>n;
    for(int i=1,u,v;i<n;i++) cin>>u>>v,e[u].push_back(v),e[v].push_back(u);
    cin>>a;
    for(int i=1,x,y;i<=a;i++) cin>>x>>y,ain[x]=max(ain[x],y);
    cin>>b;
    for(int i=1;i<=b;i++) cin>>ax[i]>>bx[i];
    dfs(1,0);
    int l=ain[1]-1,r=n+1;
    while(l+1<r){
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid;
    }
    cout<<(r>n?-1:r);
    return 0;
}

T4

因为 std 有误,所以咕了。