zoukankan      html  css  js  c++  java
  • 2017-6-11 NOIP模拟赛

    盘子序列

    【题目描述】

    n 个盘子。盘子被生产出来后,被按照某种顺序摞在一起。初始盘堆中如果一

    个盘子比所有它上面的盘子都大,那么它是安全的,否则它是危险的。称初始盘堆为

    A,另外有一个开始为空的盘堆 B。为了掩盖失误,生产商会对盘子序列做一些“处

    ” ,每次进行以下操作中的一个:(1)A 最上面的盘子放到 B 最上面;(2)B 最上

    面的盘子给你。 在得到所有n个盘子之后, 你需要判断初始盘堆里是否有危险的盘子。

    【输入格式】

    输入文件包含多组数据(不超过 10 组)

    每组数据的第一行为一个整数 n

    接下来 n 个整数,第 i 个整数表示你收到的第 i 个盘子的大小

    【输出格式】

    对于每组数据,如果存在危险的盘子,输出J”,否则输出”Y

    【样例输入】

    3

    2 1 3

    3

    3 1 2

    【样例输出】

    Y

    J

    【数据范围】

    20%的数据保证 n<=8

    80%的数据保证 n<=1,000

    100%的数据保证 1<=n<=100,0000<盘子大小<1,000,000,000 且互不相等

    模拟,考试的时候想着双栈排序那道题,就考虑到,当且仅当i<j<k&&a[j]<a[k]<a[i]是不能用单栈排序(i位于三者最底层),好像和这个题是同样的道理,所以就这么写出来了,没多想,考完顿悟了,这个做法复杂度O(n^2),还不如开个栈模拟

    /*考完试一气之下写的这个丑代码我也不想说什么了,感觉像在乱搞*/
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define maxn 100010
    int n,top1,top2,top3;
    struct node{
        int num,rank,id;
    }a[maxn],b[maxn];
    int cmp1(node x,node y){
        return x.num>y.num;
    }
    int cmp2(node x,node y){
        return x.id<y.id;
    }
    int main(){
        freopen("disk.in","r",stdin);
        freopen("disk.out","w",stdout);
        while(scanf("%d",&n)!=EOF){
            bool flag=0;
            memset(a,0,sizeof(a));top1=0;top2=0;top3=1;
            for(int i=1;i<=n;i++)scanf("%d",&a[++top1].num),a[top1].id=i;
            sort(a+1,a+n+1,cmp1);
            for(int i=1;i<=n;i++)a[i].rank=i;
            sort(a+1,a+n+1,cmp2);
            while(top1>=1){
                int t1=top1,t2=top2,t3=top3;
                while(top2!=0&&b[top2].rank==top3){
                    top3++;top2--;
                }
                if(a[top1].rank==top3){
                    top3++;top1--;
                }
                else{
                    while(a[top1].rank!=top3&&b[top2].rank!=top3){
                        if(top1<=0){
                            flag=1;break;
                        }
                        b[++top2]=a[top1--];
                    }
                }
                if(t1==top1&&t2==top2&&t3==top3){
                    break;
                }
                if(flag==1)break;
            }
            while(top2!=0&&b[top2].rank==top3){
                    top3++;top2--;
            }
            if(flag==1)printf("J
    ");
            else if(top3!=n+1){
                printf("J
    ");
            }
            else printf("Y
    ");
        }
    }

    四轮车

    【题目描述】

    在地图上散落着 n 个车轮,小 J 想用它们造一辆车。要求如下:

    1. 一辆车需要四个车轮,且四个车轮构成一个正方形

    2. 车轮不能移动

    你需要计算有多少种造车的方案 (两个方案不同当且仅当所用车轮不全相同,

    标相同的两个车轮视为不同车轮)

    【输入格式】

    第一行一个整数 n

    接下来 n 行,每行两个整数 x y,表示在(x,y)处有一个车轮

    【输出格式】

    一行一个整数,表示方案数

    【样例输入】

    9

    0 0

    1 0

    2 0

    0 2

    1 2

    2 2

    0 1

    1 1

    2 1

    【样例输出】

    6

    【数据范围】

    30%的数据保证 n ≤ 30

    100%的数据保证 1 ≤ n ≤ 1000;|x|,|y| < 20000

    考试的时候把这题当成数学题了,上来就考虑正方形的性质,什么四条边相等啊,临边垂直啊,对角线垂直啊,然后就开始写了,也没觉得有什么不妥,但是这个方法超级麻烦,写完之后样例过了,代码丑的要死,结果爆空间。

    正解是枚举两个点判断其余的两个点是否存在(只考虑枚举到的点为对角线上的点的情况),问题很好解决了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 10010
    using namespace std;
    int n,ans[maxn];
    int x1,x2,x3,x4,y1,y2,y3,y4,xx[maxn],yy[maxn],p1,p2;
    struct node{
        int x,y;
    }P[maxn];
    int cmp(node a,node b){
        return a.x<b.x;
    }
    int Abs(int a){
        return a<0?(-a):a;
    }
    void add(){
        ans[1]++;
        for(int i=1;i<=ans[0];i++)
            if(ans[i]>9){
                ans[i]%=10;
                ans[i+1]++;
            }
        if(ans[ans[0]+1])ans[0]++;
    }
    void Cal(int i,int j){
        x1=xx[i];
        y1=yy[i];
        x2=xx[j];
        y2=yy[j];
        int a=Abs(y1-y2),b=Abs(x1-x2);
        int c=Abs(a-b);
        if(c%2)
            x3=x4=y3=y4=0;
        else{
            c>>=1;
            if(a<b){
                x3=x1+c;
                y3=y2+c;
                x4=x2-c;
                y4=y1-c;
            }
            else{
                x3=x1-c;
                y3=y2-c;
                x4=x2+c;
                y4=y1+c;
            }
        }
    }
    bool Judge(){
        if(!x3&&!x4&&!y3&&!y4)
            return 0;
        int falg=0,flag=0;
        p1=lower_bound(xx+1,xx+1+n,x3)-xx;
        p2=upper_bound(xx+1,xx+1+n,x3)-xx;
        for(int i=p1;i<p2;i++){
            if(xx[i]!=x3)
                return 0;
            if(yy[i]==y3){
                falg=1;
                break;
            }
        }
        p1=lower_bound(xx+1,xx+1+n,x4)-xx;
        p2=upper_bound(xx+1,xx+1+n,x4)-xx;
        for(int i=p1;i<p2;i++){
            if(xx[i]!=x4)
                return 0;
            if(yy[i]==y4){
                flag=1;
                break;
            }
        }
        return falg&&flag;
    }
    int main()
    {
        freopen("car.in","r",stdin);
        freopen("car.out","w",stdout);
        scanf("%d",&n);
        ans[0]=1;
        for(int i=1;i<=n;i++)
            scanf("%d%d",&P[i].x,&P[i].y);
        sort(P+1,P+1+n,cmp);
        for(int i=1;i<=n;i++){
            xx[i]=P[i].x;
            yy[i]=P[i].y;
        }
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++){
                if(yy[i]>=yy[j])
                    continue;
                Cal(i,j);
                if(Judge())
                    add();
            }
        for(int i=ans[0];i>=1;i--)
            printf("%d",ans[i]);
        return 0;
    }

    点名

    【题目描述】

    J班的体育课上, 同学们常常会迟到几分钟, 但体育老师的点名却一直很准时。

    老师只关心同学的身高, 他会依次询问当前最高的身高, 次高的身高, 第三高的身高,

    等等。在询问的过程中,会不时地有人插进队伍里。你需要回答老师每次的询问。

    【输入格式】

    第一行两个整数 n m,表示先后有 n 个人进队,老师询问了 m

    第二行 n 个整数,第 i 个数 Ai 表示第 i 个进入队伍的同学的身高为 Ai

    第三行 m 个整数,第 j 个数 Bj 表示老师在第 Bj 个同学进入队伍后有一次询问

    【输出格式】

    m 行,每行一个整数,依次表示老师每次询问的答案。数据保证合法

    【样例输入】

    7 4

    9 7 2 8 14 1 8

    1 2 6 6

    【样例输出】

    9

    9

    7

    8

    【样例解释】

    (9){No.1 = 9}; (9 7){No.2 = 9}; (9 7 2 8 14 1){No.3 = 7; No.4 = 8}

    【数据范围】

    40%的数据保证 n ≤ 1000

    100%的数据保证 1 ≤ m ≤ n ≤ 30000;0 ≤ Ai < 2^32

    看到这个题,纠结于死难写死难写的主席树。

    黄学长用的方法和树毛线关系也没有,我学了来

    维护前K大的大根堆 A

    维护其余的小根堆 B

    插入:A.insert() B.insert(A.pop())

    询问:ans = A.top(); A.insert(B.pop())

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    typedef int real;
    #define int long long 
    #define pa pair<int,int>
    #define inf 1000000000
    using namespace std;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    priority_queue<int,vector<int>,greater<int> >q1;
    priority_queue<int,vector<int> >q2;
    int n,m;
    int a[30005],b[30005];
    real main()
    {
        freopen("rollcall.in","r",stdin);
        freopen("rollcall.out","w",stdout);
        n=read();m=read();
        for(int i=1;i<=n;i++)a[i]=read();
        for(int i=1;i<=m;i++)b[i]=read();
        for(int t=1;t<=m;t++)
        {
            for(int j=b[t-1]+1;j<=b[t];j++)
            {
                q2.push(a[j]);
                q1.push(q2.top());q2.pop();
            }
            q2.push(q1.top());q1.pop();
            printf("%I64d
    ",q2.top());
        }
        return 0;
    }
  • 相关阅读:
    ural 1146. Maximum Sum(动态规划)
    ural 1119. Metro(动态规划)
    ural 1013. K-based Numbers. Version 3(动态规划)
    Floyd算法
    杭电21题 Palindrome
    杭电20题 Human Gene Functions
    杭电15题 The Cow Lexicon
    杭电三部曲一、基本算法;19题 Cow Bowling
    杭电1002 Etaoin Shrdlu
    Qt 学习之路 2(37):文本文件读写
  • 原文地址:https://www.cnblogs.com/thmyl/p/6985204.html
Copyright © 2011-2022 走看看