zoukankan      html  css  js  c++  java
  • 计蒜之道2018复赛

    待续。。。

    A题

    考虑任意两个一次函数,哪个放在里面更有

    y=ax+b和y=cx+d;

    sort时满足(ax+b)x+d>(cx+d)x+b即可,在O(n)计算即可

    D题

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #define maxn 100002
    using namespace std;
    int inf[2],s[2][maxn],fa[maxn],now,ans;
    vector<int>e[maxn];
    char is[20];
    bool vis[maxn],ind[maxn],ct[maxn],ex[maxn];
    inline int find(int x) {return fa[x]==x?x: fa[x]=find(fa[x]);}
    inline void unionn(int u,int v){
          int x=find(u),y=find(v);
          if(x!=y)fa[x]=y;
          return ;
    }
    inline bool dfs(int u){
          ind[u]=1;
          vis[u]=1;
          int flag=0,siz=e[u].size();
          for(int p=0;p<siz;p++){
              if(ind[e[u][p]]){flag=1;continue;}
              if(vis[e[u][p]])continue;
              if(dfs(e[u][p])) flag=1;
          }
          ind[u]=0;
          return flag;
      }
    int main(){
        int n;scanf("%d",&n);
        for(int i=0;i<2;i++){
            scanf("%s",is);
            if(strcmp(is,"Constant")==0)inf[i]=0;else inf[i]=1;
            for(int j=1;j<=n;j++)scanf("%d",&s[i][j]);
        }
        if(inf[0]==0)now=1;else now=0;
        int pt=inf[0]+inf[1];
        for(int i=1;i<=100000;i++)fa[i]=i;
        for(int i=1;i<=n;i++){
            if(pt>=1 && s[now][i]!=s[now^1][i])e[s[now][i]].push_back(s[now^1][i]),unionn(s[now][i],s[now^1][i]);
            ex[s[now][i]]=1;ex[s[now^1][i]]=1;
        }
        ans=0;
        for(int i=1;i<=100000;i++){
            if(e[i].size()>0){
                sort(e[i].begin(),e[i].end());
                e[i].resize(unique(e[i].begin(),e[i].end())-e[i].begin());
            }
            if(ex[i])ans++;
        }
        if(pt==0){
            bool flag=0;
            for(int i=1;i<=n;i++)if(s[0][i]!=s[1][i])flag=1;
            if(flag)printf("-1
    ");else printf("0
    ");
        }
        if(pt==1){
            for(int i=1;i<=100000;i++)if(ex[i] && !vis[i])if(dfs(i))ct[find(i)]=1;
            for(int i=1;i<=100000;i++)if(ex[i] && fa[i]==i && ct[i]==0)ans--;
            printf("%d
    ",ans);
        }
        if(pt==2){
            for(int i=1;i<=100000;i++)if(ex[i] && fa[i]==i)ans--;
            printf("%d
    ",ans);
        }
        return 0;
    }

    E题

    发现这题好简单,考场上看到通过的人那么少就不敢打了 m^-w-^m

    将一个点拆成两个点,维护最大值和最小值,因为a会小于0

    若一个值被更新了2*n次,那么就肯定能达到无穷大或无穷小

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    const long long inf=2e14;
    const int maxn=5002;
    const int maxm=10002;
    int n,m,cnt,flag,head[maxn],tot[maxm];
    bool vis[maxn];
    queue<int>q;
    struct node{long long maxn,minn;}a[maxn];
    struct data{int v,nex,a,b;}edge[maxm];
    inline int read(){
        char ch=getchar();int x=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*=f;
    }
    inline void addedge(int u,int v,int a,int b){edge[++cnt].v=v;edge[cnt].a=a;edge[cnt].b=b;edge[cnt].nex=head[u];head[u]=cnt;}
    inline void spfa(){
        long long tmp1,tmp2,tmp;int x,v;
        while(!q.empty())q.pop();
        q.push(1);vis[1]=1;tot[1]++;tot[1+n]++;
        while(!q.empty()){
            x=q.front();q.pop();vis[x]=0;
            for(int i=head[x];i;i=edge[i].nex){
                v=edge[i].v;
                if(a[x].maxn==inf){if(edge[i].a>0)tmp1=inf;if(edge[i].a==0)tmp1=1LL*edge[i].b;if(edge[i].a<0)tmp1=-inf;}
                else tmp1=1LL*edge[i].a*a[x].maxn+1LL*edge[i].b;
                if(a[x].minn==-inf){if(edge[i].a>0)tmp2=-inf;if(edge[i].a==0)tmp2=1LL*edge[i].b;if(edge[i].a<0)tmp2=inf;}
                else tmp2=1LL*edge[i].a*a[x].minn+1LL*edge[i].b;
                if(tmp1>tmp2){tmp=tmp1;tmp1=tmp2;tmp2=tmp;}
                if(tmp1<a[v].minn){
                    a[v].minn=tmp1;tot[v]++;if(tot[v]>2*n)a[v].minn=-inf;
                    if(!vis[v]){vis[v]=1;q.push(v);}
                }
                if(tmp2>a[v].maxn){
                    a[v].maxn=tmp2;tot[v+n]++;if(tot[v+n]>2*n)a[v].maxn=inf;
                    if(!vis[v]){vis[v]=1;q.push(v);}
                }
                if(v==n)flag=1;
            }
        }
    }
    int main(){
        int T,x0,x1,x2,x3;T=read();
        while(T--){
            n=read();m=read();cnt=flag=0;
            a[1].maxn=a[1].minn=0;for(int i=2;i<=n;i++){a[i].maxn=-inf;a[i].minn=inf;}
            for(int i=1;i<=m;i++){x0=read();x1=read();x2=read();x3=read();addedge(x0,x1,x2,x3);}
            spfa();
            if(!flag)printf("No solution
    ");else if(a[n].maxn==inf)printf("Infinity
    ");else printf("%lld
    ",a[n].maxn);
            for(int i=1;i<=n;i++)head[i]=0,vis[i]=0;
            for(int i=1;i<=2*n;i++)tot[i]=0;
        }
        return 0;
    }

    G题

    逆元处理下

    1、统计‘a'~'z'各自出现次数(cnt数组记录)

    2.遍历一遍t串,将其中出现的字母先固定t串,cnt[ t[ i ] ]--;

    3, ans=(lens-lent+1)*!(lens-lent)/(!cnt[1~26)

  • 相关阅读:
    正则表达式(Python3-re模块示例)
    format函数之几种常规用法
    元组的拆包
    Python3魔术方法实现一摞卡牌
    Python字典的常见操作
    70. Climbing Stairs(js)
    69. Sqrt(x)(js)
    68. Text Justification(js)
    67. Add Binary(js)
    66. Plus One(js)
  • 原文地址:https://www.cnblogs.com/MikuKnight/p/9200639.html
Copyright © 2011-2022 走看看