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("\n");
                continue;
            }
            for(int i=0;i<cnt-1;i++)
            printf("%d ",s[i]);
            printf("%d",s[cnt-1]);
            printf("\n");
        }
        else{
            for(int i=0;i<tot-1;i++)
            printf("%d ",s1[i]);
            printf("%d",s1[tot-1]);
            printf("\n");
        }
   }
}
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\n",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\n");
        else printf("Yes\n");
    }
}
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\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2020-09-26 21:58  朝暮不思  阅读(176)  评论(0编辑  收藏  举报