zoukankan      html  css  js  c++  java
  • 6.30模拟赛

    1.盘子序列(disk)

    【题目描述】

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

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

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

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

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

    【输入格式】

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

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

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

    【输出格式】

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

    【样例输入】

    3

    2 1 3

    3

    3 1 2

    【样例输出】

    Y

    【数据范围】

    20%的数据保证 n<=8

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

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

    思路:

      STL~ 栈。。。

      题目告诉我们手中收到盘子的顺序,让我们来推断A堆的盘子顺序,从而判断A堆是否是安全的,我们可以换一种思路,我们假设A堆是安全的,那么如果通过操作能得到收盘子的顺序,那么就是安全的,否则是危险的!!!

      如果当前堆是安全的,那么在下面的盘子一定比上面的大!!

      仔细阅读,不难发现题目中的两个操作就是进栈和出栈的操作,所以我们将盘子从小到大一边压栈一边与出栈顺序比较,如果相同就出栈,否则继续新元素继续进栈,直到相同在出栈,我们会发现如果最后栈中的元素数是>1时,说明不能得到当前所给的出栈顺序,所以不安全,否则,安全。。

    上代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<stack>
    using namespace std;
    
    const int maxx = 100003;
    int n,dish[maxx],A[maxx],num,tot,step[maxx];
    stack<int>s;
    
    int main() {
        freopen("disk.in","r",stdin);
        freopen("disk.out","w",stdout);
        while(scanf("%d",&n)!=EOF) {
            while(!s.empty()) s.pop();
            for(int i=1; i<=n; i++) {
                scanf("%d",&dish[i]);
                step[i] = dish[i];
            }
            sort(step+1,step+n+1);
            int num = 1,tot = 1;
            s.push(step[num]);
            while(tot<=n && num<=n) {
                int top = s.top();
                if(top == dish[tot]) 
                    tot++,s.pop();
                else s.push(step[num+1]),num++; 
                if(s.empty()) 
                    s.push(step[num+1]),num++; 
            }
            if(s.size()>1) cout<<"J"<<endl;
            else cout<<"Y"<<endl;
        }
        fclose(stdin),fclose(stdout);
        return 0;
    }

    2.四轮车

    【题目描述】

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

    1. 一辆车需要四个车轮,且四个车轮构成一个正方形
    1. 车轮不能移动你需要计算有多少种造车的方案(两个方案不同当且仅当所用车轮不全相同,坐标相同的两个车轮视为不同车轮)。

    【输入格式】

    第一行一个整数 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

     思路:

      我们确定正方形两个点,去枚举正方形的另外两个点,我们知道两点的坐标,去表示另两点的坐标,但是正方形可能是与x、y轴平行的,也可能不是,所以我们分三种情况讨论。。。

      pair<int,int>ZB, first表示该点的横坐标,second表示纵坐标,set一一映射,判断点是否存在轮胎

    上代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<utility>
    #include<cstdlib>
    #include<set>
    using namespace std;
    
    typedef pair<int,int>ZB;
    ZB jz[1003],a1,a2,step;
    int n,x,y,a,b,c,d;
    set<ZB>S;
    long long ans;
    
    
    void solve(int i,int j) {
        a=jz[i].first,b=jz[i].second,c=jz[j].first,d=jz[j].second;
        if(a == c) { //已知坐标的横坐标相等 ,在同一列 
            a1.first=a+abs(d-b),a1.second=b,a2.first=c+abs(d-b),a2.second=d;
            if(S.count(a1) && S.count(a2)) ans++;//S.count()如果集合中有这个元素返回1,否则返回0 
            a1.first=a-abs(d-b),a1.second=b,a2.first=c-abs(d-b),a2.second=d;
            if(S.count(a1) && S.count(a2)) ans++;
        }
        else if(b == d) { //已知坐标的纵坐标相等,在同一行 
            a1.first=a,a1.second=b+abs(a-c),a2.first=c,a2.second=d+abs(a-c);
            if(S.count(a1) && S.count(a2)) ans++;
            a1.first=a,a1.second=b-abs(a-c),a2.first=c,a2.second=d-abs(a-c);
            if(S.count(a1) && S.count(a2)) ans++;
        }
        else { //正方形与x、y轴不平行 
            a1.first=a-abs(d-b),a1.second=d+abs(a-c),a2.first=a+abs(a-c),a2.second=d+abs(d-b);
            if(S.count(a1) && S.count(a2)) ans++;
            a1.first=a+abs(d-b),a1.second=d-abs(a-c),a2.first=a-abs(a-c),a2.second=d-abs(d-b);
            if(S.count(a1) && S.count(a2)) ans++;
        }
    }
    
    int main() {
        //freopen("car10.in","r",stdin);
        //freopen("car.out","w",stdout);
        scanf("%d",&n);
        for(int i=1; i<=n; i++) {
            scanf("%d%d",&jz[i].first,&jz[i].second);
            step.first = jz[i].first, step.second = jz[i].second;
            S.insert(step); 
        }
        for(int i=1; i<=n; i++) {
            for(int j=1; j<=n; j++) {
                if(i == j) continue;
                solve(i,j);
            }
        }
        printf("%d",ans/8);//每个正方形有四个点,一条边可扩展2个正方形,所以答案/8 
        fclose(stdin); fclose(stdout);
        return 0;
    }

    3.点名

    【题目描述】

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

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

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

    【输入格式】

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

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

    第三行个整数,第个数 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 < 232

    思路:

      1.考场暴力sort,70分(当然,这是在用long long的情况下,数据太TM坑人了)

      2.大根堆与小根堆的巧妙结合(AC)

      3.主席树(AC,可是偶不会2333。。。

    大根堆与小根堆的巧妙结合:

    一个小根堆q1,一个大根堆q2

    q2维护当前最小的k个值

    所以每次的答案就是q2的堆顶

    对于每次询问,

    枚举上一次入队到这一次入队的人

    向q2中加入这个人的高度,q1中加入q2的堆顶,删除q2堆顶

    即加入新的,删除最大的,保持q2中始终是当前最小的k个

    因为这个k是上一次询问的k

    所以最后把q1的堆顶加入q2,删除q1堆顶

    所以q1是小根堆

     

    坑:数据 2^32 是long long

    上代码:

    #include<iostream>
    #include<cstdio>
    #include<queue> 
    using namespace std;
    
    priority_queue<long long,vector<long long>,greater<int> >qx;
    priority_queue<long long>qd;
    
    long long n,m,hight[30003],ask[30003];
    
    int main() {
        freopen("rollcall10.in","r",stdin);
        freopen("rollcall.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++) {
            scanf("%d",&hight[i]);
        }
        for(int i=1; i<=m; i++) {
            scanf("%d",&ask[i]);
        }
        for(int i=1; i<=m; i++) {
            for(int j=ask[i-1]+1; j<=ask[i]; j++) {
                qd.push(hight[j]);
                qx.push(qd.top()),qd.pop(); 
            }
            qd.push(qx.top()),qx.pop(); 
            printf("%I64d
    ",qd.top());
        }
        fclose(stdin);fclose(stdout);
        return 0;
    }

    自己选的路,跪着也要走完!!!

  • 相关阅读:
    小*号
    进制转换升级版
    对角线的值
    使用Arduino开发板控制步进电机
    使用VisualGDB和OpenOCD调试STM32L0开发板
    基于STM32L476开发板的USB音频设备
    【FRDM-K64F学习笔记】使用ARM mbed和Keil MDK下载你的第一个程序
    使用超声波传感器HC-SR04检测障碍物
    使用Atmel Studio编程Arduino Uno开发板
    重新编程Hexiwear Docking Station扩展坞
  • 原文地址:https://www.cnblogs.com/wsdestdq/p/7101482.html
Copyright © 2011-2022 走看看