• 2020中国计量大学校赛题解


    这个比赛读题时间过长,做题时间比较少,一直在机械的打代码,没有做到后面值得思考的题目,有点可惜

    A题 树链剖分维护到根节点的答案即可

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2e5+10;
    int n,m;
    int h[N],ne[N],e[N],idx;
    int id[N],w[N],pre[N],top[N],times;
    int fa[N],sz[N],son[N],depth[N];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    struct node{
        int l,r;
        ll sum;
    }tr[N];
    void dfs(int u){
        int i;
        sz[u]=1;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==fa[u])
                continue;
            fa[j]=u;
            depth[j]=depth[u]+1;
            dfs(j);
            sz[u]+=sz[j];
            if(sz[j]>sz[son[u]]){
                son[u]=j;
            }
        }
    }
    void dfs1(int u,int x){
        pre[u]=++times;
        id[times]=u;
        top[u]=x;
        if(!son[u])
            return;
        dfs1(son[u],x);
        int i;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==fa[u]||j==son[u])
                continue;
            dfs1(j,j);
        }
    }
    void build(int u,int l,int r){
        if(l==r){
            tr[u]={l,r,0};
        }
        else{
            tr[u]={l,r,0};
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
        }
    }
    void pushup(int u){
        tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
    }
    void modify(int u,int l,int x){
        if(tr[u].l==tr[u].r){
            tr[u].sum+=x;
            return ;
        }
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)
            modify(u<<1,l,x);
        else
            modify(u<<1|1,l,x);
        pushup(u);
    }
    ll query(int u,int l,int r){
        if(tr[u].l>=l&&tr[u].r<=r){
            return tr[u].sum;
        }
        int mid=tr[u].l+tr[u].r>>1;
        ll res=0;
        if(l<=mid)
            res+=query(u<<1,l,r);
        if(r>mid)
            res+=query(u<<1|1,l,r);
        return res;
    }
    ll qpath(int x,int y){
        ll res=0;
        while(top[x]!=top[y]){
            if(depth[top[x]]<depth[top[y]])
                swap(x,y);
            res=res+query(1,pre[top[x]],pre[x]);
            x=fa[top[x]];
        }
        if(depth[x]>depth[y])
            swap(x,y);
        res=res+query(1,pre[x],pre[y]);
        return res;
    }
    int main(){
        ios::sync_with_stdio(false);
        cin>>n>>m;
        int i;
        memset(h,-1,sizeof h);
        int rt=0;
        for(i=1;i<=n;i++){
            int x;
            cin>>x;
            if(x!=0){
                add(i,x);
                add(x,i);
            }
            if(!x){
                rt=i;
            }
        }
        depth[rt]=1;
        fa[rt]=0;
        dfs(rt);
        dfs1(rt,rt);
        build(1,1,n);
        while(m--){
            int u,x,v;
            cin>>u>>x>>v;
            cout<<qpath(v,rt)<<endl;
            modify(1,pre[u],x);
        }
    }
    View Code

    B题 从前往后枚举,主要要和变成0的情况去min

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int s[123456];
    int s1[123456];
    int cnt,tot;
    int main(){
       int t;
       scanf("%d",&t);
       while(t--){
        cnt=0;
        s1[0]=0;
        tot=1;
        string a,b;
        string c="";
        cin>>a>>b;
        for(int i=0;i<(int)a.size();i++)c+="0";
    
            int z=0;
            for(int i=0;i<(int)a.size();i++){
                int aa=a[i]-'0',bb=b[i]-'0';
                if((aa+z)%2!=bb){
                    s[cnt++]=i+1;
                    z++;
                }
            }
            z=0;
            for(int i=0;i<(int)c.size();i++){
                int aa=c[i]-'0',bb=b[i]-'0';
                if((aa+z)%2!=bb){
                    s1[tot++]=i+1;
                    z++;
                }
            }
            if(cnt<tot){
                if(!cnt){
                    printf("
    ");
                    continue;
                }
                for(int i=0;i<cnt-1;i++)
                printf("%d ",s[i]);
                printf("%d",s[cnt-1]);
                printf("
    ");
            }
            else{
                for(int i=0;i<tot-1;i++)
                printf("%d ",s1[i]);
                printf("%d",s1[tot-1]);
                printf("
    ");
            }
       }
    }
    View Code

    C题 模拟水题

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int a[27];
    struct node{
        ll l,r;
    }s[N];
    int main(){
        ios::sync_with_stdio(false);
        int t;
        cin>>t;
        while(t--){
            int n;
            cin>>n;
            ll ans=0;
            ll tmp=0;
            int i;
            for(i=1;i<=n;i++){
                cin>>s[i].l>>s[i].r;
            }
            for(i=1;i<=n;i++){
                if(tmp>=s[i].l&&tmp<=s[i].r){
                    ans++;
                }
                else{
                    if(s[i].r<tmp){
                        ans+=(tmp-s[i].r);
                        tmp=s[i].r;
                        ans++;
                    }
                    else{
                        ans+=(s[i].l-tmp);
                        tmp=s[i].l;
                        ans++;
                    }
                }
            }
            cout<<ans<<endl;
        }
    }
    View Code

    D题 猜结论

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int a[123456];
    int s[123456];
    int cnt;
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
                cnt=0;
            int n;scanf("%d",&n);
            for(int i=0;i<n;i++){
                scanf("%d",&a[i]);
            }
            sort(a,a+n);
            for(int i=0,j=0;i<n;i=j){
                while(a[j]==a[i]&&j<n)j++;
                if((j-i)%2==1)s[cnt++]=a[i];
            }
            if(!cnt){
                cout<<a[0]<<endl;
            }
            else if(cnt==1){
                cout<<-1<<endl;
            }
            else if(cnt==2){
                cout<<s[0]<<endl;
            }else{
                cout<<s[cnt-1]<<endl;
            }
        }
    }
    View Code

    E题 

    F题 输出答案

    H题 线段树区间修改

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    struct node{
        int l,r;
        int mx;
        int lazy;
    }tr[N<<2];
    int a[N];
    int n,m;
    void pushup(int u){
        tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx);
    }
    void build(int u,int l,int r){
        if(l==r){
            tr[u]={l,r,a[l],-1};
        }
        else{
            tr[u]={l,r,0,-1};
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
            pushup(u);
        }
    }
    void pushdown(int u){
        int x=tr[u].lazy;
        tr[u<<1].mx=tr[u<<1|1].mx=x;
        tr[u<<1].lazy=tr[u<<1|1].lazy=x;
        tr[u].lazy=-1;
    }
    void modify(int u,int l,int r,int x){
        if(tr[u].l>=l&&tr[u].r<=r){
            tr[u].mx=0;
            tr[u].lazy=x;
            return ;
        }
        if(tr[u].lazy!=-1)
            pushdown(u);
        int mid=tr[u].l+tr[u].r>>1;
        if(l<=mid)
            modify(u<<1,l,r,x);
        if(r>mid)
            modify(u<<1|1,l,r,x);
        pushup(u);
    }
    int main(){
        //ios::sync_with_stdio(false);
        int t;
        cin>>t;
        while(t--){
            scanf("%d%d",&n,&m);
            int i;
            for(i=1;i<=n;i++)
                scanf("%d",&a[i]);
            build(1,1,n);
            while(m--){
                int l,r;
                scanf("%d%d",&l,&r);
                modify(1,l,r,0);
                printf("%d
    ",tr[1].mx);
    
            }
        }
    }
    View Code

    I题 祖冲之点集

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    int a[27];
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            int n;
            scanf("%d",&n);
            if(n<=2)printf("No
    ");
            else printf("Yes
    ");
        }
    }
    View Code

    J题 dfs染色

    显然看出二分单调性,对于check函数,需要设计一下

    我们通过反向考虑,对两个点边大于权值的建边,之后进行染色看是否存在冲突。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=2e5+10;
    const int inf=1e9+7;
    vector<pll> s[N];
    vector<int> g[N];
    int vis[N];
    int n,m;
    int dfs(int u,int fa,int x){
        int i;
        vis[u]=x;
        for(i=0;i<(int)g[u].size();i++){
            int j=g[u][i];
            if(j==fa)
                continue;
            if(vis[j]==vis[u])
                return 0;
            if(vis[j]==(vis[u]^1))
                continue;
            if(vis[j]==-1){
                if(!dfs(j,u,!x))
                    return 0;
            }
    
        }
        return 1;
    }
    bool check(int d){
        int i;
        for(i=0;i<=n;i++){
            g[i].clear();
            vis[i]=-1;
        }
        for(i=1;i<=n;i++){
            for(auto x:s[i]){
                if(x.second>d){
                    g[i].push_back(x.first);
                }
            }
        }
        int flag=1;
        for(i=1;i<=n;i++){
            if(vis[i]==-1){
                flag=dfs(i,-1,0);
                if(!flag){
                    return 0;
                }
            }
        }
        return 1;
    }
    int main(){
        int t;
        ios::sync_with_stdio(false);
        cin>>t;
        while(t--){
            cin>>n>>m;
            int i,j;
            for(i=0;i<=n;i++)
                s[i].clear();
            for(i=1;i<=m;i++){
                int a,b,c;
                cin>>a>>b>>c;
                s[a].push_back({b,c});
                s[b].push_back({a,c});
            }
            int l=0,r=inf;
            while(l<r){
                int mid=l+r>>1;
                if(check(mid)){
                    r=mid;
                }
                else{
                    l=mid+1;
                }
            }
            cout<<l<<endl;
        }
        return 0;
    }
    View Code

    K1题 模拟

    #include<cstdio>
    #include<iostream>
    #include<string>
    using namespace std;
    int a[13]= {0,31,0,31,30,31,30,31,31,30,31,30,31};
    
    bool check(int n)
    {
        if(n%400==0||(n%4==0&&n%100!=0))
            return true;
        return false;
    }
    
    int main()
    {
        string s;
        while(getline(cin,s)&&s[0]!='#')
        {
            int ans=0;
            int i=0;
            while((i+7)<(int)s.length())
            {
                for(;s[i+7]!=' '&&(i+7)<(int)s.length(); i++)
                {
                    if(s[i]==s[i+7]&&s[i+1]==s[i+6]&&s[i+2]==s[i+5]&&s[i+3]==s[i+4])
                    {
                        int y,m,d;
                        d=(s[i+7]-'0')+(s[i+6]-'0')*10;
                        m=(s[i+5]-'0')+(s[i+4]-'0')*10;
                        y=(s[i+3]-'0')+(s[i+2]-'0')*10+(s[i+1]-'0')*100+(s[i]-'0')*1000;
                        if(check(y))
                            a[2]=29;
                        else
                            a[2]=28;
                        if(y>0&&m>0&&d>0&&m<=12&&d<=a[m])
                            ans++;
                    }
                }
                if(s[i+7]==' ')
                    i=i+7;
                while(s[i]==' ')
                    i++;
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    C#实现函数根据返回类型重载
    自己动手实现Expression翻译器 – Part Ⅱ
    ld编译链接时默认搜索路径
    出游
    常用网络命令(转贴)
    redhat6.3企业版安装oracle11g过程
    sqlserver2000版本识别
    考IQ的推断题-生日几何?
    Microsoft Visual Studio .NET 系统必备
    101~200之间的素数
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13736963.html
Copyright © 2020-2023  润新知