A. Escalator Conversations

题意:dddd

思路:暴力枚举

diamond:

#include<bits/stdc++.h>
using namespace  std;
#define int long long
void solve(){
    int n,m,k,h;
    cin>>n>>m>>k>>h;
    int ans=0;
    for (int i = 0; i < n; ++i) {
        int x;
        cin>>x;
        int g=abs(x-h);

        if(g%k==0){
//            cout<<g<<endl;
            if(g/k<m&&g/k>0){
                ans++;
            }
        }

    }
    cout<<ans<<endl;

}
signed main(){
    int t;
    cin>>t;
    while (t--){
        solve();
    }
}

B. Parity Sort

题意:给定一个无序序列,奇偶性相同的数字才能交换位置,问能否把他变为有序的

思路:菜鸡思路:记录这个数字的排完序后的位置,然后映射一下,如果他本身的位置和他最终的位置不同,就是no。大佬思路:直接排序,看当前数字与原本数字奇偶性是否相同,直接判断,tqltql

diamond:

#include<bits/stdc++.h>
using namespace  std;
#define int long long
bool cmp1(pair<int,int>x,pair<int,int>y){
    if(x.first!=y.first)
    return x.first<y.first;
    return x.second<y.second;
}
bool cmp2(pair<int,int>x,pair<int,int>y){
    return x.second<y.second;
}
void solve(){
    int n;
    cin>>n;
    vector<pair<int,int>>g(n+1);
    vector<int>a(n+1);
    for (int i = 1; i <=n ; ++i) {
        cin>>g[i].first;
        a[i]=g[i].first;
        g[i].second=i;
    }
    sort(g.begin(),g.end(),cmp1);
    for (int i = 1; i <=n ; ++i) {
        g[i].first=i;
    }
    sort(g.begin(),g.end(),cmp2);
    int vis=1;
    for (int i = 1; i <=n ; ++i) {
    if(a[i]%2!=a[g[i].first]%2){
            vis=0;
        }
    }
    if(vis){
        cout<<"YES\n";
    }
    else{
        cout<<"NO\n";
    }

}
signed main(){
    int t;
    cin>>t;
    while (t--){
        solve();
    }
}

C. Tiles Comeback

题意:balabalabalabala,其实就是要求与起点相同的数字是否有k个,与终点相同的数字是否有k个,且前者的最后一个的位置$≤$ 后者的第一个位置。

思路:就是题意

diamond:

#include<bits/stdc++.h>
using namespace  std;
#define int long long
void solve(){
    int n,k;
    cin>>n>>k;
    vector<int>q(n+1);
    for (int i = 1; i <=n ; ++i) {
        cin>>q[i];
    }
    if(q[1]==q[n]){
        int ans=0;
        for (int i = 1; i <=n ; ++i) {
            if(q[i]==q[1]){
                ans++;
            }
        }
        if(ans>=k){
            cout<<"YES\n";
            return;
        }
        else{
            cout<<"NO\n";
            return;
        }
    }
    int cnt1=0,dq=n+1;
    for (int i = 1; i <=n ; ++i) {
        if(q[i]==q[1]){
            cnt1++;
        }
        if(cnt1==k){
            dq=i;
            break;
        }
    }
    int cnt2=0;
    for (int i = n; i >=1 ; --i) {
        if(q[i]==q[n]){
            cnt2++;
        }
        if(cnt2==k){
            if(i>=dq){
                cout<<"YES\n";
                return;
            }
            else{
                cout<<"NO\n";
                return;
            }
        }
    }
    cout<<"NO\n";
}
signed main(){
    int t;
    cin>>t;
    while (t--){
        solve();
    }
}

D. Prefix Permutation Sums

题意:给一个少了一个位置的前缀和数组,问原序列有没有可能是1到n的序列

思路:求一下后一个减前一个。分为三种情况

  • 第一种是没有1的情况,少的那个前缀和是头部,如果少的那两个数字和为q[1],那么即可以
  • 第二种情况是尾部为答案,首位是原序列中的数字,那么我们就少了一个数字,我们check一下,如果少了一个数字,那么就是yes
  • 第三种情况是缺少了中间的一个前缀点,两数加起来是大于n的,check一下少的那两个数的和是否是最大的那个值

    diamond:

    #include<bits/stdc++.h>
    using namespace  std;
    #define int long long
    void solve(){
    int n;
    cin>>n;
    vector<int >q(n+1);
    map<int,int>mp;
    for (int i = 1; i <n ; ++i) {
        cin>>q[i];
        if(i>1)
        mp[q[i]-q[i-1]]++;
    }
    int vis=1;
    for (auto i:mp) {
        if(i.second>1){
            vis=0;
            break;
        }
    }
    if(vis){
        ///没1的缺一的情况
        int cnt=0;
        int sum=0;
        for (int i = 1; i <=n ; ++i) {
            if(mp[i]==0){
                cnt++;
                sum+=i;
            }
        }
        if(cnt==2&&sum==q[1]){
            cout<<"YES\n";
            return;
        }
    }
    //首位为原序列的情况,尾部为答案,少了一个尾部
    map<int,int>mp2;
    for (int i = 1; i <n ; ++i) {
        mp2[q[i]-q[i-1]]++;
    }
    int vis2=1;
    for (auto i:mp2) {
            if(i.second>1){
               vis2=0;
                break;
            }
    }
    if(vis2){
        int cnt=0;
        for (int i = 1; i <=n ; ++i) {
            if(mp2[i]==0){
                cnt++;
            }
        }
        if(cnt==1){
            cout<<"YES\n";
            return;
        }
    }
    ////缺了两个中间的大于n的答案
    map<int,int>mp3;
    int ma=-1;
    for (int i = 1; i <n ; ++i) {
        if(mp3[q[i]-q[i-1]]>0||q[i]-q[i-1]>n){
            ma=q[i]-q[i-1];
        }
        mp3[q[i]-q[i-1]]=1;
    
    }
    //    cout<<q[1]<<' '<<q[0];
    //    cout<<ma<<' ';
    int ans=0;
    int cnt3=0;
    for (int i = 1; i <=n ; ++i) {
    //        cout<<mp[i]<<' ';
        if(!mp3[i]){
            ans+=i;
            cnt3++;
        }
    }
    //    cout<<ans<<' ';
    if(ans==ma&&cnt3==2){
        cout<<"YES\n";
        return;
    }
    cout<<"NO\n";
    }
    signed main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    }

    E. Nastya and Potions

    题意:需要制成n种药剂,每种药剂的价格给出,然后有k种药剂是免费的无限的,第i 种药品可以由某几种药品制成,问每一个药剂的最小单价是多少

    思路:

  • 思路1:利用dfs深搜遍历每一个可以到达的点,如果这个点没有儿子,那么说明他的ans就是原价,其他的有儿子的原价与儿子的和进行取min即可

  • 思路2:用一个药品的材料来连接这个药品,然后找拓扑序,当入度为0时,我们就可以求一下ans。

    diamond:

  • 思路1

    #include<bits/stdc++.h>
    using namespace  std;
    #define int long long
    void solve(){
    int n,m;
    cin>>n>>m;
    vector<int>a(n+1);
    for (int i = 1; i <=n ; ++i) {
        cin>>a[i];
    }
    vector<int>q[n+1];
    for (int i = 0; i <m ; ++i) {
        int x;
        cin>>x;
        a[x]=0;
    }
    for (int i = 1; i <=n ; ++i) {
        int k;
        cin>>k;
        while(k--){
            int y;
            cin>>y;
            if(i!=y)
            q[i].push_back(y);
        }
    }
    vector<int>ans(n+1);
    vector<bool>vis(n+1);
    function<void (int)>dfs=[&](int u){
        ans[u]=a[u];
        int res=1e18;
        if(q[u].size()!=0)res=0;
        for (auto i:q[u]) {
            if(vis[i]){
                res+=ans[i];
                continue;
            }
            vis[i]=1;
            dfs(i);
            res+=ans[i];
        }
        ans[u]=min(ans[u],res);
    };
    
    for (int i = 1; i <=n ; ++i) {
        if(vis[i])continue;
        vis[i]=true;
        dfs(i);
    }
    for (int i = 1; i <=n ; ++i) {
        cout<<ans[i]<<' ';
    }
    cout<<'\n';
    }
    signed main(){ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    }


  • 思路2:

    #include<bits/stdc++.h>
    using namespace  std;
    #define int long long
    void solve(){
    int n,m;
    cin>>n>>m;
    vector<int>a(n+1);
    vector<int>d(n+1);
    for (int i = 1; i <=n ; ++i) {
        cin>>a[i];
    }
    vector<int>q[n+1];
    for (int i = 0; i <m ; ++i) {
        int x;
        cin>>x;
        a[x]=0;
    }
    for (int i = 1; i <=n ; ++i) {
        int k;
        cin>>k;
        while(k--){
            int y;
            cin>>y;
                q[y].push_back(i),d[i]++;
        }
    }
    queue<int>st;
    vector<int>ans(n+1);
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(d[i]==0) {
            st.push(i), cnt++;
            ans[i]=a[i];
        }
    }
    
    while(st.size()){
        auto t=st.front();
        st.pop();
        ans[t]=min(a[t],ans[t]);
        for(int i=0;i<q[t].size();i++){
            auto g=q[t][i];
            d[g]--;
            ans[g]+=ans[t];
            if(d[g]==0){
                st.push(g);
            }
        }
    }
    for (int i = 1; i <=n ; ++i) {
        cout<<ans[i]<<' ';
    }
    cout<<endl;
    }
    signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    }

    F. Lisa and the Martians

    题意:我们的答案$(a_i \oplus x) \& (a_j \oplus x)$可以简化成当我们x取最大,全部取1时,我们只需让$a[i]$^$a[j]$最小即可,我们可以证明当x<y<z时,x^z是>=x^y||y^z的,因此我们排序后,取异或最小&111111,或者同或最大与&0000000即可

    diamond:

    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    bool cmp(pair<int,int>x,pair<int,int>y){
    if(x.first==y.first)return x.second<y.second;
    return x.first<y.first;
    }
    void solve(){
    int n,k;
    cin>>n>>k;
    vector<pair<int,int> >q(n+1);
    //    map<int,int>mp;
    for(int i=1;i<=n;i++) {
        cin >> q[i].first;
        q[i].second = i;
    }
    
    sort(q.begin()+1,q.end());
    //    cout<<endl;
    int ma=(1ll<<k)-1;
    //    cout<<ma<<endl;
    int l,r;
    int res=INT_MAX,ans;
    for (int i = 2; i <=n ; ++i) {
        if(res>(q[i].first^q[i-1].first)){
            res=(q[i].first^q[i-1].first);
            l=q[i].second,r=q[i-1].second;
            ans = ma ^ ( q[i].first | q[i-1].first);
        }
    }
    cout<<l<<' '<<r<<' '<<ans<<endl;
    }
    signed main(){
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    }

    G. Vlad and the Mountains

    题意:n个山,高度是h[i],爬山消耗能量b-a,下山恢复能量b-a,q次询问,问初始能量为c时,能否从a山到达b山

    思路:从1-2-3-4-5,能否从1到5,其实是问能否从1到其中的最高的一座山。从a到可以到b,则h[a]+e>=h_max;我们可以把边按照边权从小到大排序,然后我们开始进行合并,我们将边进行合并,把所有小于等于h[a]+e的边进行合并,那么这次询问我们就可以得到答案,因为边的合并次数就只是m次,当我们合并h[a]+e较小的那些时,我们合并的边,当遍历到更大的询问时,我们就不用合并之前的了,因为较小的能够到达的我们已经记录过了,所以如果按询问的h[a]+e从小到达排,那我们合并的次数就不会重复,连通性我们用并查集来维护,所以我们将询问的顺序也排序,记录idx即可,x1<x2<x3,当我们处理x2时,x2包括x1,那么我们就只需要处理$!(x2∩x1)$这个集合的边,处理x3时,也是只需要处理x3中$ !(x2∩x3)$,这样就可以做到一个$O(M)$的复杂度,如果这俩点在一个集合中,那么就是YES

    diamond:

    
    #pragma GCC optimize(1)
    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline")
    #pragma GCC optimize("-fgcse")
    #pragma GCC optimize("-fgcse-lm")
    #pragma GCC optimize("-fipa-sra")
    #pragma GCC optimize("-ftree-pre")
    #pragma GCC optimize("-ftree-vrp")
    #pragma GCC optimize("-fpeephole2")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-fsched-spec")
    #pragma GCC optimize("unroll-loops")
    #pragma GCC optimize("-falign-jumps")
    #pragma GCC optimize("-falign-loops")
    #pragma GCC optimize("-falign-labels")
    #pragma GCC optimize("-fdevirtualize")
    #pragma GCC optimize("-fcaller-saves")
    #pragma GCC optimize("-fcrossjumping")
    #pragma GCC optimize("-fthread-jumps")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-freorder-blocks")
    #pragma GCC optimize("-fschedule-insns")
    #pragma GCC optimize("inline-functions")
    #pragma GCC optimize("-ftree-tail-merge")
    #pragma GCC optimize("-fschedule-insns2")
    #pragma GCC optimize("-fstrict-aliasing")
    #pragma GCC optimize("-falign-functions")
    #pragma GCC optimize("-fcse-follow-jumps")
    #pragma GCC optimize("-fsched-interblock")
    #pragma GCC optimize("-fpartial-inlining")
    #pragma GCC optimize("no-stack-protector")
    #pragma GCC optimize("-freorder-functions")
    #pragma GCC optimize("-findirect-inlining")
    #pragma GCC optimize("-fhoist-adjacent-loads")
    #pragma GCC optimize("-frerun-cse-after-loop")
    #pragma GCC optimize("inline-small-functions")
    #pragma GCC optimize("-finline-small-functions")
    #pragma GCC optimize("-ftree-switch-conversion")
    #pragma GCC optimize("-foptimize-sibling-calls")
    #pragma GCC optimize("-fexpensive-optimizations")
    #pragma GCC optimize("inline-functions-called-once")
    #pragma GCC optimize("-fdelete-null-pointer-checks")
    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=2e5+10;
    int h[N],fa[N];
    struct node{
    int a,b,w;
    };
    struct query{
    int a,b,h_max,idx;
    };
    bool cmp1(node x,node y){
    return x.w<y.w;
    }
    bool cmp2(query x, query y){
    return x.h_max<y.h_max;
    }
    int find (int x){
    if(x!=fa[x]){
        fa[x]=find(fa[x]);
    }
    return fa[x];
    }
    void solve(){
    vector<node>edge;
    vector<query>Q;
    int n,m;
    cin>>n>>m;
    for (int i = 1; i <=n ; ++i) {
        cin>>h[i];
    }
    
    for (int i = 0; i <m ; ++i) {
        int a,b;
        cin>>a>>b;
        edge.push_back({a,b,max(h[a],h[b])});
    }
    int q;
    cin>>q;
    sort(edge.begin(),edge.end(),cmp1);
    vector<bool>ans(q);
    for (int i = 0; i <=n ; ++i) {
        fa[i]=i;
    }
    for (int i = 0; i <q ; ++i) {
        int a,b,e;
        cin>>a>>b>>e;
        Q.push_back({a,b,h[a]+e,i});
    }
    sort(Q.begin(),Q.end(),cmp2);
    int cnt=0;
    for (int i = 0; i <q ; ++i) {
        while (cnt<m&&Q[i].h_max>=edge[cnt].w){
            int pa=find(edge[cnt].a),pb=find(edge[cnt].b);
            if(pa!=pb){
                fa[pa]=pb;
            }
            cnt++;
        }
        if(find(Q[i].a)==find(Q[i].b)){
            ans[Q[i].idx]=true;
        }
        else{
            ans[Q[i].idx]=false;
    
        }
    }
    for (int i = 0; i <q ; ++i) {
        if(ans[i]){
            cout<<"YES\n";
        }
        else{
            cout<<"NO\n";
        }
    }
    cout<<'\n';
    }
    signed main()
    {ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while (t--)solve();

}

posted on 2023-07-28 16:34  IR101  阅读(9)  评论(0编辑  收藏  举报  来源