zoukankan      html  css  js  c++  java
  • 7.10

    CF380C Sereja and Brackets

    题意:

      给一个只有左右括号的序列和n段区间,求每个序列区间中最长的匹配括号子序列的长度。

    思路:

      线段树,记录每个区间中未匹配的左括号的未匹配的右括号的个数,寻找区间是都是从左往右找,最后答案就是区间长度-1-未匹配的左右括号个数

    code:

    #include<cstdio>
    #define N 1000000
    using namespace std;
    struct arr{
        int l,r,a,b;
    }tr[N*4];
    int ri,le,n,l;
    char s[N];
    void build(int w,int l,int r){
        tr[w].l=l,tr[w].r=r;
        if (l==r){
            if (s[l-1]=='(') tr[w].a++;
            else tr[w].b++;
            return;
        }
        int mid=(l+r)/2;
        build(w*2,l,mid);
        build(w*2+1,mid+1,r);
        tr[w].a=tr[w*2+1].a;
        tr[w].b=tr[w*2].b;
        if (tr[w*2].a>tr[w*2+1].b)
            tr[w].a+=(tr[w*2].a-tr[w*2+1].b);
        else tr[w].b+=(tr[w*2+1].b-tr[w*2].a);
    }
    void find(int w,int l,int r){
        if (tr[w].l==l&&tr[w].r==r){
            if (tr[w].b<=le) le-=tr[w].b;
            else ri+=tr[w].b-le,le=0;
            le+=tr[w].a;
            return;
        }
        int mid=(tr[w].l+tr[w].r)/2;
        if (r<=mid) find(w*2,l,r);
        else if (l>mid) find(w*2+1,l,r);
        else{
            find(w*2,l,mid);
            find(w*2+1,mid+1,r); 
        }
    }
    int main(){
        scanf("%s",&s);
        for (l=0;s[l]!='';l++);
        build(1,1,l);
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            int x,y;
            le=ri=0;
            scanf("%d%d",&x,&y);
            find(1,x,y);
            printf("%d
    ",y-x+1-le-ri);
        }
    } 

    CF1366D Two Divisors

    题意:

      给出n个数字,判断每个数字a是否存在两个因数d1>1和d2>1,满足gcd(d1+d2,a)=1,没有则输出两个-1

    思路:

      每个数字都可以分成p1^k1*p2^k2*p3^k3... (p1<p2<p3...)

      则a的因数有a/(p1^k1)和p1,则a/(p1^k1)+p1与p1,p2,p3任何一个都互质

    code:

    #include<cstdio>
    #include<algorithm>
    #define N 10000000
    using namespace std;
    int s[N+7],n,a[N+7],b[N+7];
    bool f[N+7];
    int main(){
        for (int i=1;i<=N;i++)
            s[i]=i;
        for (int i=2;i<=N;i++)
            if (!f[i])
                for (int j=2;j<=N/i;j++){
                    f[i*j]=true;
                    s[i*j]=min(s[i*j],i);
                }
        scanf("%d",&n);
        for (int i=1;i<=n;i++){
            int x,y;
            scanf("%d",&x);
            y=x;
            a[i]=b[i]=1;
            while ((x%s[y])==0){
                a[i]*=s[y];
                x/=s[y];
            }
            if (x==1)
                a[i]=b[i]=-1;
            else b[i]=x;
        }
        for (int i=1;i<=n;i++)
            printf("%d ",a[i]);
        printf("
    ");
        for (int i=1;i<=n;i++)
            printf("%d ",b[i]);
    }

    CF1370D Odd-Even Subsequence

    题意:

      给出一个长度为n序列,你可以将序列删剩m个数字,使得奇数位置的最大值和偶数位置的最大值的最小值最小。

    题意:

      这种题目求最大值最小的可以考虑二分,判断能否简洁的取到m/2个不大于mid的值,还要考虑m的奇偶。

    code:

    #include<cstdio>
    #include<algorithm>
    #define N 200007
    using namespace std;
    int n,m,ma,a[N],l,r,mid;
    bool check1(int x){
        int p=0;
        if (m%2==1)
            for (int i=2;i<n;i++){
                if (a[i]<=x) p++,i++;
            }
        else
            for (int i=2;i<=n;i++){
                if (a[i]<=x) p++,i++;
            }
        if (p>=m/2) return true;
        return false;
    }
    bool check2(int x){
        int p=0;
        if (m%2==1)
            for (int i=1;i<=n;i++){
                if (a[i]<=x) p++,i++;
            }
        else
            for (int i=1;i<n;i++){
                if (a[i]<=x) p++,i++;
            }
        if (p>=(m+1)/2) return true;
        return false;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            r=max(a[i],r);
        }
        l=1;
        while (l<r){
            mid=(l+r)/2;
            if (check1(mid)||check2(mid))
                r=mid;
            else l=mid+1;
        }
        printf("%d
    ",l);
    }

    CF2B The least round way

    题意:

      给出一个n*n个矩阵,从左上角走到右上角,求路线中所有数之积结尾0的个数最少的个数,并输出路线

    题意:

      结尾有0就是2*5,分别求2最少时min(2的个数,5的个数)和5最少时min(2的个数,5的个数),有一个特殊情况就是有0,如果有0且最终结果大于1,那就输出1,路线是要通过0的位置

    code:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define N 1007
    using namespace std;
    int n,a[N][N],h[N][N],t[N][N],p1[N][N],p2[N][N],c1[N][N],c2[N][N],ans;
    char d1[N][N],d2[N][N],p[N*2];
    void check1(){
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++){
                int x1=p1[i-1][j],y1=p1[i][j-1];
                int x2=c2[i-1][j],y2=c2[i][j-1];
                if (i==1) x1=x2=0xffffff;
                if (j==1) y1=y2=0xffffff;
                if (x1<y1||(x1==y1)&&(p2[i-1][j]<=p2[i][j-1]))
                    p1[i][j]=h[i][j]+p1[i-1][j],p2[i][j]=t[i][j]+p2[i-1][j],d1[i][j]='D';
                else p1[i][j]=h[i][j]+p1[i][j-1],p2[i][j]=t[i][j]+p2[i][j-1],d1[i][j]='R';
                if (x2<y2||(x2==y2)&&(c1[i-1][j]<=c1[i][j-1]))
                    c1[i][j]=h[i][j]+c1[i-1][j],c2[i][j]=t[i][j]+c2[i-1][j],d2[i][j]='D';
                else c1[i][j]=h[i][j]+c1[i][j-1],c2[i][j]=t[i][j]+c2[i][j-1],d2[i][j]='R';
            }
        int k1=min(p1[n][n],p2[n][n]),k2=min(c1[n][n],c2[n][n]);
        ans=min(k1,k2);
        int x=n,y=n;
        for (int i=2*n-2;i>=1;i--){
            if (k1<=k2) p[i]=d1[x][y];
            else p[i]=d2[x][y];
            if (p[i]=='D') x--;
            else y--;
        }
    }
    int main(){
        scanf("%d",&n);
        int g[50],e[30];
        g[0]=e[0]=1;
        for (int i=1;i<=26;i++)
            g[i]=g[i-1]*2;
        for (int i=1;i<=11;i++)
            e[i]=e[i-1]*5;
        bool q=false;
        int bx,by;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++){
                scanf("%d",&a[i][j]);
                if (a[i][j]==0) q=true,bx=i,by=j;
                for (int s=26;s>=0;s--)
                    if (a[i][j]%g[s]==0){
                        h[i][j]=s;
                        a[i][j]/=g[s];
                        break;
                    }
                for (int s=11;s>=0;s--)
                    if (a[i][j]%e[s]==0){
                        t[i][j]=s;
                        a[i][j]/=e[s];
                        break;
                    }
            }
        check1();
        if (q&&ans>1){
            printf("1
    ");
            for (int i=1;i<bx;i++)
                printf("D");
            for (int i=1;i<n;i++)
                printf("R");
            for (int i=1;i<=n-bx;i++)
                printf("D");
            return 0;
        }
        printf("%d
    ",ans);
        for (int i=1;i<=2*n-2;i++)
            printf("%c",p[i]);
        printf("
    ");
    } 
  • 相关阅读:
    SSH框架学习笔记(六)----hibernate关联映射注解
    1. Elasticsearch startup on local
    Oracle PL/SQL 入门
    单例模式的两种实现方式对比:DCL (double check idiom)双重检查 和 lazy initialization holder class(静态内部类)
    单例模式中用volatile和synchronized来满足双重检查锁机制
    Java反射机制可以动态修改实例中final修饰的成员变量吗?
    left join 条件区别
    Java应用程序项目的打包与发行(run.bat形式)
    Eclipse调试常用技巧(转)
    PhoneGap: Android 自定义组件
  • 原文地址:https://www.cnblogs.com/Tokisaki-Kurumi/p/14993663.html
Copyright © 2011-2022 走看看