Codeforces Round #756 (Div. 3)

A. Make Even

题目:

思路分析:

就是如何把一个数变为偶数 只能取其前缀进行reverse

如果没有偶数位 那么就不可能

偶数位在第一个 那么直接r1次everse就行

如果在中间的话 2次 

代码实现:

#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<list>
#include<set>
#include<iomanip>
#include<cstring>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cassert>
#include<sstream>
#include<algorithm>

using namespace std;
typedef long long  ll;
#define re register //局部
#define PI atan(1.0)*4
#define ull unsigned long long
#define scf(n) scanf("%d",&n)
#define scfl(n) scanf("%lld",&n)
#define prf(n) printf("%d",n)
#define prfl(n) printf("%lld",n)
#define scfd(n) scanf("%lf",&n)
#define prfd(n) printf("%.lf",n)
#define prf10(n) printf("%.10f",n)
#define ls (rt<<1)
#define rs (rt<<1|1)
//#define mid (l+r)/2
#define mms(x, y) memset(x, y, sizeof x)
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
const int INF = 0x3f3f3f3f;
const double EPS=1e-10;
const double Pi=3.1415926535897;
using namespace std;


int t;
int main(){
    cin>>t;
    while (t--) {
        string s;
        cin>>s;
        int pos=-1;

        for(int i=0;i<s.size();i++){
            if ((s[i]-'0')%2==0) {
                pos=i;
                break;
            }
        }
        if((s[s.size()-1]-'0')%2==0){
            cout<<0<<endl;
        }
        else if(pos==-1){
            cout<<-1<<endl;
        }
        else if(pos==0){
            cout<<1<<endl;
        }
        else cout<<2<<endl;
        
    }
}

B. Team Composition: Programmers and Mathematicians

题目:

思路分析:

也是一道规律题目

每种物品不少于1件 一共4件为一套

那么直接min((a+b )/4,a,b)就行

代码实现:

#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<list>
#include<set>
#include<iomanip>
#include<cstring>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cassert>
#include<sstream>
#include<algorithm>

using namespace std;
typedef long long  ll;
#define re register //局部
#define PI atan(1.0)*4
#define ull unsigned long long
#define scf(n) scanf("%d",&n)
#define scfl(n) scanf("%lld",&n)
#define prf(n) printf("%d",n)
#define prfl(n) printf("%lld",n)
#define scfd(n) scanf("%lf",&n)
#define prfd(n) printf("%.lf",n)
#define prf10(n) printf("%.10f",n)
#define ls (rt<<1)
#define rs (rt<<1|1)
//#define mid (l+r)/2
#define mms(x, y) memset(x, y, sizeof x)
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
const int INF = 0x3f3f3f3f;
const double EPS=1e-10;
const double Pi=3.1415926535897;
using namespace std;

int t;
ll a,b;
int main(){
    cin>>t;
    while (t--) {
        cin>>a>>b;
        ll ans=min(a,b);
        ans=min(ans,(a+b)/4);
        cout<<ans<<endl;
    }
}

C. Polycarp Recovers the Permutation

题目:

思路分析:

一道构造题目

就是一个序列 如果取原序列的左右最小数字 放到新序列的对应的左面 或者右面

那么我们可以发现最大的数字一定在最左或者最右

然后把其他位直接reverse就行

最大位放最后面

代码实现:

#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<list>
#include<set>
#include<iomanip>
#include<cstring>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cassert>
#include<sstream>
#include<algorithm>

using namespace std;
typedef long long  ll;
#define re register //局部
#define PI atan(1.0)*4
#define ull unsigned long long
#define scf(n) scanf("%d",&n)
#define scfl(n) scanf("%lld",&n)
#define prf(n) printf("%d",n)
#define prfl(n) printf("%lld",n)
#define scfd(n) scanf("%lf",&n)
#define prfd(n) printf("%.lf",n)
#define prf10(n) printf("%.10f",n)
#define ls (rt<<1)
#define rs (rt<<1|1)
//#define mid (l+r)/2
#define mms(x, y) memset(x, y, sizeof x)
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
const int INF = 0x3f3f3f3f;
const double EPS=1e-10;
const double Pi=3.1415926535897;
using namespace std;

int t;
const int MAX=2e5+10;
int a[MAX];
int main(){
    cin>>t;
    while (t--) {
        int n;
        cin>>n;
        int m=-0x3f3f3f3f;
        int id=-1;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            if(a[i]>m){
                m=a[i];
                id=i;
            }
        }
        if(id>1&&id<n){
            cout<<-1<<endl;
        }
        else {
            for(int i=n;i>=1;i--){
                if(a[i]!=m){
                    cout<<a[i]<<" ";
                }
            }
            cout<<m<<endl;
            
        }
    }
}

E1. Escape The Maze (easy version)

题目:

思路分析:

题意就是一个人和k个鬼 人位于树的根上 然后人要逃到这棵树的叶子结点上 但是途中不能碰到鬼

鬼的最优策略是每次都走到自己的父节点

对于每个节点 可以考虑到到该节点最近的鬼与该点的深度相比 如果该节点的深度小于鬼到该点的距离 那么该点就可以安全通过

那么我们直接从根节点跑一遍dfs就行 

代码实现:


#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<list>
#include<set>
#include<iomanip>
#include<cstring>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cassert>
#include<sstream>
#include<algorithm>

using namespace std;
typedef long long  ll;
#define re register //局部
#define PI atan(1.0)*4
#define ull unsigned long long
#define scf(n) scanf("%d",&n)
#define scfl(n) scanf("%lld",&n)
#define prf(n) printf("%d",n)
#define prfl(n) printf("%lld",n)
#define scfd(n) scanf("%lf",&n)
#define prfd(n) printf("%.lf",n)
#define prf10(n) printf("%.10f",n)
#define ls (rt<<1)
#define rs (rt<<1|1)
//#define mid (l+r)/2
#define mms(x, y) memset(x, y, sizeof x)
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
const int INF = 0x3f3f3f3f;
const double EPS=1e-10;
const double Pi=3.1415926535897;
using namespace std;

int t;
const int MAX=2e5+10;
int n,k;
int vis[MAX];
int de[MAX];
int di[MAX];
vector<int>v[MAX];
int dfs(int u,int dep){
    vis[u]=1;
    int flag=0;
    if(u!=1&&v[u].size()==1&&de[u]) return 1;
    for(int i=0;i<v[u].size();i++){
        int to=v[u][i];
        if(vis[to]) continue;
        if(dfs(to,dep+1)) flag=1;
        de[u]=min(de[u],de[to]+1);
    }
    if(flag&&dep<de[u]) {
        return 1;
    }
    return 0;
}
void init(){
    for(int i=1;i<=n;i++){
        v[i].clear();
        vis[i]=0;
        de[i]=0x3f3f3f3f;
    }
}
void solve(){
    
    cin>>n>>k;
    init();
    for(int i=1;i<=k;i++){
        int x;
        cin>>x;
        de[x]=0;
    }
    for(int i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    if(dfs(1,0)){
        cout<<"YES"<<endl;
    }
    else cout<<"NO"<<endl;
}
int main(){
    cin>>t;
    while (t--) {
        solve();
    }
    return 0;
}

D. Weights Assignment For Tree Edges

题目:

思路分析:

算是一道构造题吧!

给你一个序列 如果按照对应序列的数字遍历 其dist是递增的

 我们很容易发现 序列第一个必须是树的根 因为其权值最小

然后按照 序列中的第i个点的权值为i那么每个点和他父亲连边的权值为他的值-他父亲的值

然后按照序列的顺序去遍历 如果该点还没有赋值说明了 其父亲的权值大于其权值 那么边权就是负值 return-1就行

代码实现:


#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<list>
#include<set>
#include<iomanip>
#include<cstring>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cassert>
#include<sstream>
#include<algorithm>

using namespace std;
typedef long long  ll;
#define re register //局部
#define PI atan(1.0)*4
#define ull unsigned long long
#define scf(n) scanf("%d",&n)
#define scfl(n) scanf("%lld",&n)
#define prf(n) printf("%d",n)
#define prfl(n) printf("%lld",n)
#define scfd(n) scanf("%lf",&n)
#define prfd(n) printf("%.lf",n)
#define prf10(n) printf("%.10f",n)
#define ls (rt<<1)
#define rs (rt<<1|1)
//#define mid (l+r)/2
#define mms(x, y) memset(x, y, sizeof x)
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
const int INF = 0x3f3f3f3f;
const double EPS=1e-10;
const double Pi=3.1415926535897;
using namespace std;


const int MAX=2e5+10;
int t;
int n;
int fa[MAX];
int ans[MAX];
int p[MAX];
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>fa[i];
    for(int i=1;i<=n;i++) cin>>p[i],ans[i]=0;
    if(p[1]!=fa[p[1]]){
        cout<<-1<<endl;
        return;
    }
    ans[p[1]]=1;
    for(int i=2;i<=n;i++){
        if(!ans[fa[p[i]]]){
            cout<<-1<<endl;
            return;
        }
        ans[p[i]]=i;
    }
    for(int i=1;i<=n;i++){
        cout<<ans[i]-ans[fa[i]]<<" ";
    }
    cout<<endl;
}
int main(){
    cin>>t;
    while (t--) {
        solve();
    }
}

E2. Escape The Maze (hard version)

题目:

思路分析:

题意就是需要多少个鬼才能抓到人

和之前的思路差不多一样

同样对所有节点中要考虑子树中所有点的最近的鬼到该点的距离与该节点的深度相比

如果深度大于等于鬼到这点的距离的话 那么给子树只需要这一个鬼就可以守到

否则的话需要该子树所有的鬼之和

如果存在一个子树不可以守住那么就输出-1

代码实现:


#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<list>
#include<set>
#include<iomanip>
#include<cstring>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cassert>
#include<sstream>
#include<algorithm>

using namespace std;
typedef long long  ll;
#define re register //局部
#define PI atan(1.0)*4
#define ull unsigned long long
#define scf(n) scanf("%d",&n)
#define scfl(n) scanf("%lld",&n)
#define prf(n) printf("%d",n)
#define prfl(n) printf("%lld",n)
#define scfd(n) scanf("%lf",&n)
#define prfd(n) printf("%.lf",n)
#define prf10(n) printf("%.10f",n)
#define ls (rt<<1)
#define rs (rt<<1|1)
//#define mid (l+r)/2
#define mms(x, y) memset(x, y, sizeof x)
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
const int INF = 0x3f3f3f3f;
const double EPS=1e-10;
const double Pi=3.1415926535897;
using namespace std;


const int MAX=2e5+10;

int t;
int n,k;
int deep[MAX];
int vis[MAX];
vector<int>e[MAX];
void init(){
    
    for(int i=1;i<=n;i++){
        vis[i]=0;
        deep[i]=0x3f3f3f3f;
    }
}
int dfs(int u,int dep){
    vis[u]=1;
    int flag=0;
    int sum1=0;
    int sum2=0;
    if(deep[u]&&u!=-1&&e[u].size()==1){
        return -1;
    }
    for(int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if(vis[v]){
            continue;
        }
        sum2=dfs(v,dep+1);
        if(sum2==-1) flag=1;
        else sum1+=sum2;
        deep[u]=min(deep[u],deep[v]+1);
    }
    if(flag&&dep<deep[u])
        return -1;
    else if(dep>=deep[u]) return 1;
    else if(flag==0) return sum1;
    
    
}
void solve(){
    cin>>n>>k;
    init();
    for(int i=1;i<=k;i++){
        int x;
        cin>>x;
        deep[x]=0;
    }
    for(int i=1;i<n;i++){
        int a,b;
        cin>>a>>b;
        e[a].push_back(b);
        e[b].push_back(a);
    }
    cout<<dfs(1,0)<<endl;
    
}
int main(){
    cin>>t;
    while (t--) {
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭晋龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值