• Codeforces Round #361 (Div. 2) 套题


    A - Mike and Cellphone

    问有没有多解,每个点按照给出的序列用向量法跑一遍

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long LL;
    const int N=2e5+5;
    const int INF=0x3f3f3f3f;
    char s[15];
    int a[15],n;
    int mp[5][4]={-1,-1,-1,-1,
                   -1,1,2,3,
                   -1,4,5,6,
                   -1,7,8,9,
                   -1,-1,0,-1
                 };
    typedef pair<int,int> pii;
    pii pos[10];
    bool judge(int num){
      int x=pos[num].first,y=pos[num].second;
      for(int i=2;i<=n;++i){
        int px=pos[a[i]].first-pos[a[i-1]].first;
        int py=pos[a[i]].second-pos[a[i-1]].second;
        x+=px;y+=py;
        if(x<1||x>4||y<1||y>3)return false;
        if(mp[x][y]==-1)return false;
      }
      return true;
    }
    int main(){
      scanf("%d%s",&n,s+1);
      if(n==1){printf("NO
    ");return 0;}
      for(int i=1;i<=n;++i)
        a[i]=s[i]-'0';
      for(int i=1;i<=4;++i){
        for(int j=1;j<=3;++j){
          if(mp[i][j]==-1)continue;
           pos[mp[i][j]].first=i;
           pos[mp[i][j]].second=j;
        }
      }
      bool flag=false;
      for(int i=0;i<=9;++i)
        if(i!=a[1]&&judge(i)){flag=true;break;}
      if(flag)printf("NO
    ");
      else printf("YES
    ");
      return 0;
    }
    View Code

    B - Mike and Shortcuts

    可能有更优的办法,一看数据,dij最短路水过

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long LL;
    const int N=2e5+5;
    const int INF=0x3f3f3f3f;
    struct Edge{
       int v,next;
       LL w;
       Edge(int a=0,LL b=0){v=a,w=b;}
       bool operator<(const Edge &e)const{
          return w>e.w;
       } 
    }edge[N*3];
    int head[N],tot,n;
    LL d[N];
    void add(int u,int v,int w){
       edge[tot].v=v;
       edge[tot].w=w;
       edge[tot].next=head[u];
       head[u]=tot++;
    }
    priority_queue<Edge>q;
    bool vis[N];
    void dij(int s){
        for(int i=1;i<=n;++i)d[i]=INF,vis[i]=0;
        d[s]=0,q.push(Edge(s,0));
        while(!q.empty()){
           int u=q.top().v;
           q.pop();
           if(vis[u])continue;
           vis[u]=1;
           for(int i=head[u];~i;i=edge[i].next){
              int v=edge[i].v;
              if(!vis[v]&&d[v]>d[u]+edge[i].w){
                d[v]=d[u]+edge[i].w;
                q.push(Edge(v,d[v]));
              }
           } 
        }
    }
    int main(){
      scanf("%d",&n);
      memset(head,-1,sizeof(head));
      for(int i=1;i<=n;++i){
         int x;scanf("%d",&x);
         add(i,x,1);
      }
      for(int i=1;i<n;++i){
        add(i,i+1,1);
        add(i+1,i,1);
      }
      dij(1);
      for(int i=1;i<n;++i)printf("%I64d ",d[i]);
      printf("%I64d
    ",d[n]);
      return 0;
    }
    View Code

    C - Mike and Chocolate Thieves

    直接二分找就行,注意二分的移动

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long LL;
    const int N=2e5+5;
    const int INF=0x3f3f3f3f;
    LL judge(LL mid){
      LL sum=0;
      for(LL i=2;i<=1000000;++i){
       sum+=mid/(i*i*i);
      }
      return sum;
    }
    int main(){
      LL m;
      scanf("%I64d",&m);
      LL l=1,r=1ll*1e18,ret=-1;
      while(l<=r){
        LL mid=(l+r)>>1; 
        LL tmp=judge(mid);
        if(tmp>m)r=mid-1;
        else if(tmp==m)ret=mid,r=mid-1;
        else l=mid+1;
      }
      printf("%I64d
    ",ret);
      return 0;
    }
    View Code

    D - Friends and Subsequences

    这个题,不知道是我线段树写残了,还是线段树常数大,死活超时,RMQ才过,哪天去学一发ZKW线段树的姿势吧

    #include <vector>
    #include <iostream>
    #include <queue>
    #include <cmath>
    #include <map>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    #define For(i,j,n) for(int i=j;i<=n;i++)
    #define Riep(n) for(int i=1;i<=n;i++)
    #define Riop(n) for(int i=0;i<n;i++)
    #define Rjep(n) for(int j=1;j<=n;j++)
    #define Rjop(n) for(int j=0;j<n;j++)
    #define mst(ss,b) memset(ss,b,sizeof(ss));
    typedef  long long LL;
    template<class T> void read(T&num) {
        char CH; bool F=false;
        for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
        for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
        F && (num=-num);
    }
    int stk[70], tp;
    template<class T> inline void print(T p) {
        if(!p) { puts("0"); return; }
        while(p) stk[++ tp] = p%10, p/=10;
        while(tp) putchar(stk[tp--] + '0');
        putchar('
    ');
    }
    
    const LL mod=1e9+7;
    const double PI=acos(-1.0);
    const LL inf=1e18;
    const int N=2e5+10;
    const int maxn=1005;
    const double eps=1e-10;
    
    int a[N],b[N],MX[N][21],MN[N][21],n;
    struct Tree
    {
        int l,r;
        int mmax,mmin;
    }tr[4*N];
    
    void build(int o,int L,int R)
    {
        for(int i=1;i<=n;i++)
        MX[i][0]=a[i],MN[i][0]=b[i];
        for(int j=1;(1<<j)<=n;j++)
        {
            for(int i=1;i+(1<<j)-1<=n;i++)
            {
                MX[i][j]=max(MX[i][j-1],MX[i+(1<<(j-1))][j-1]);
                MN[i][j]=min(MN[i][j-1],MN[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int query(int o,int L,int R,int flag)
    {
        if(flag)
        {
            int k = 0;
            while( (1<<(k+1)) <= R-L+1) k ++ ;
            return max(MX[L][k],MX[R-(1<<k)+1][k]);
        }
        else
        {
            int k = 0;
            while( (1<<(k+1)) <= R-L+1) k ++ ;
            return min(MN[L][k],MN[R-(1<<k)+1][k]);
        }
    }
    int judge(int x,int y)
    {
        int mx=query(1,x,y,1),mn=query(1,x,y,0);
       if(mx==mn)return 1;
      else if(mx>mn)return 2;
      return 0;
      
    }
    int main()
    {
        read(n);
        For(i,1,n)read(a[i]);
        For(i,1,n)read(b[i]);
        build(1,1,n);
         LL ret=0;
      for(int i=1;i<=n;++i){
        int ans1=-1,ans2=-1;
        int l=i,r=n;
        while(l<=r){
          int m=l+r>>1;
          int t=judge(i,m);
          if(t==1)ans1=m,r=m-1;
          else if(t==2)r=m-1;
          else l=m+1;
        }
        l=i,r=n;
        while(l<=r){
          int m=l+r>>1;
          int t=judge(i,m);
          if(t==1)ans2=m,l=m+1;
          else if(t==2)r=m-1;
          else l=m+1;
        }
        if(ans1!=-1&&ans2!=-1)ret+=ans2-ans1+1;
      }
      printf("%I64d
    ",ret);
            return 0;
    }
    View Code

    E - Mike and Geometry Problem

    区间题,转化一下,看每个点被多少个线段覆盖(离散化搞搞),相同覆盖数统计,然后用组合数就行

    #include <vector>
    #include <iostream>
    #include <queue>
    #include <cmath>
    #include <map>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    using namespace std;
    typedef long long LL;
    const int N=2e5+5;
    const LL mod=1e9+7;
    struct Segment{
       int l,r;
    }p[N];
    int pos[N*2],n,k,tot,a[N*2],b[2*N];
    LL dp[N],fac[N],inv[N];
    LL quick_pow(LL a,LL num){
      LL ret=1;
      while(num){
        if(num&1)ret=(ret*a)%mod;
        num>>=1;
        a=(a*a)%mod;
      }
      return ret;
    }
    LL C(LL n,LL m){
      return (fac[n]*inv[n-m])%mod*inv[m]%mod;
    }
    int main()
    {
        scanf("%d%d",&n,&k);    
        inv[0]=fac[0]=1;
        for(int i=1;i<=n;++i){
            fac[i]=1ll*i*fac[i-1]%mod;
            inv[i]=quick_pow(fac[i],mod-2);
        } 
        for(int i=1;i<=n;++i){
          scanf("%d%d",&p[i].l,&p[i].r);
          pos[++tot]=p[i].l;
          pos[++tot]=p[i].r;
        }
        sort(pos+1,pos+1+tot);
        tot=unique(pos+1,pos+1+tot)-pos-1;
        for(int i=1;i<=n;++i){
          p[i].l=lower_bound(pos+1,pos+1+tot,p[i].l)-pos;
          p[i].r=lower_bound(pos+1,pos+1+tot,p[i].r)-pos;
          ++a[p[i].l],--b[p[i].r];
        }
        for(int i=1;i<=tot;++i){
          a[i]+=a[i-1];
          ++dp[a[i]];
          if(i!=1)dp[a[i-1]]+=max(0,pos[i]-pos[i-1]-1);
          a[i]+=b[i];
        }
        LL ret=0;
        for(int i=k;i<=n;++i){
           ret=(ret+dp[i]*C(i,k)%mod)%mod;
        }
        printf("%I64d
    ",ret);
        return 0;
    }
    View Code
  • 相关阅读:
    python不同包之间调用时提示文件模块不存在的问题
    adb shell 查看内存信息
    adb shell top 使用
    Android读取logcat信息
    父类的引用对象指向子类的对象
    我的阿里梦——淘宝前端必备技能
    我也做了一个1/4圆形菜单
    可编辑tab选项卡
    canvas 之
    canvas之----浮动小球
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5660110.html
Copyright © 2020-2023  润新知