Codeforces Round #582 (Div. 3)部分题解

E. Two Small Strings

题意

给你 n n n a 、 b 、 c a、b、c abc,组成一个字符串
并且给定两个长度为2的字符串,使得你得到的串没有这个子串。

题解

构造一组 a b c abc abc的全排列,重复 n n n次,每种字符串最多 6 6 6个子串,一旦出现相同的,就可以交换位置,如果还会出现相同的可以继续交换位置,因为只有两个这样做是绰绰有余的,不会出现交换两次之后会出现之前的子串的。

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e6+50;
 
int main(){
    int n;
    string s,t;
    cin>>n>>s>>t;
    string abc="abc";
    vector<string>res;
    do{
        string cur;
        FOR(i,1,n)cur+=abc;
        res.push_back(cur);
        res.push_back(string(n,abc[0])+string(n,abc[1])+string(n,abc[2]));
    }while(next_permutation(abc.begin(),abc.end()));
    for(auto str:res){
        if(str.find(s)==string::npos&&str.find(t)==string::npos){
            cout<<"YES"<<endl<<str<<endl;
            return 0;
        }
    }
    cout<<"NO"<<endl;
    return 0;
}

F. Unstable String Sort

题意

给你两个序列,构造一个字符串。
使得 a [ p i ] &lt; = a [ p i + 1 ] a[p_i]&lt;=a[p_{i+1}] a[pi]<=a[pi+1]

题解

核心在于不同的部分,如果这两部分的值不相同的话,一定不满足条件,所以容易证明,对于一段区间内两个数组的数构成的集合相同的话,就是全部相同的。
按照这样构造即可,集合相同可以用 s e t set set处理,每次加入之前判断有没有,有的话选择删,如果set大小为 0 0 0说明形成了这样的集合。

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
 
string str;
set<int>st;
int A[maxn],B[maxn];
 
int main(){
    str="";
    int n,k;
    cin>>n>>k;
    FOR(i,1,n)scanf("%d",&A[i]);
    FOR(i,1,n)scanf("%d",&B[i]);
    int pos=-1,cnt=0;
    for(int i=1;i<=n;i++){
        if(st.find(A[i])!=st.end())st.erase(A[i]);
        else st.insert(A[i]);
        if(st.find(B[i])!=st.end())st.erase(B[i]);
        else st.insert(B[i]);
        cnt++;
        if(st.empty()){
            if(pos+1<26){
                FOR(j,1,cnt)str+=char('a'+pos+1);
                pos++;
            }
            else FOR(j,1,cnt)str+='z';
            cnt=0;
        }
    }
    string ans=str;
    if(pos+1>=k){
        cout<<"YES"<<endl;
        for(int i=1;i<=n;i++){
            ans[A[i]-1]=str[i-1];
        }
        cout<<ans<<endl;
    }
    else puts("NO");
}
 

G. Path Queries

题意

求树上点对,满足点对之间的所有边的最大边小于等于 k k k
处理多个询问

题解

可以离线做,按边权把所有边加进去,对于已经形成连通块的部分,显然任意取两个点都可以。
然后就结束了

#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
 
struct node{
    int from,to,dist;
    friend bool operator < (node a,node b){
        return a.dist<b.dist;
    }
}A[maxn];
 
struct query{
    int x,id;
    friend bool operator < (query a,query b){
        return a.x<b.x;
    }
}Q[maxn];
 
ll ans[maxn];
int f[maxn],sz[maxn];
 
int find(int x){return f[x]==x?x:(f[x]=find(f[x]));}
 
int main(){
    int n,m;
    cin>>n>>m;
    FOR(i,1,n-1){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        A[i]=node{u,v,w};
    }
    FOR(i,1,n)f[i]=i,sz[i]=1;
    sort(A+1,A+n);
    int pos=0;ll now=0;
    FOR(i,1,m)scanf("%d",&Q[i].x),Q[i].id=i;
    sort(Q+1,Q+1+m);
    FOR(i,1,m){
        while(pos<n-1&&A[pos+1].dist<=Q[i].x){
            pos++;
            int u=find(A[pos].from),v=find(A[pos].to);
            now-=1ll*sz[u]*(sz[u]-1)/2+1ll*sz[v]*(sz[v]-1)/2;
            sz[u]+=sz[v];
            f[v]=u;
            now+=1ll*sz[u]*(sz[u]-1)/2;
        }
        ans[Q[i].id]=now;
    }
    FOR(i,1,m)printf("%lld ",ans[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值