zoukankan      html  css  js  c++  java
  • 170611 NOIP模拟赛

    第一题没做出来不应该;

    第二题不难想,就是写起来很麻烦;

    第三题因为学了挺久的splay就直接写的splay,没太在意常数问题,一般情况下,第k值问题主席树是比splay稍快的;

    盘子序列

    【题目描述】

    有 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,000,0<盘子大小<1,000,000,000 且互不相等

    思路

    倒序栈模拟;

    代码实现

     1 #include<cstdio>
     2 #include<cstring>
     3 const int maxn=1e5+10;
     4 int n;
     5 int a[maxn],b[maxn],bs,c[maxn],cs;
     6 int main(){
     7     freopen("disk.in","r",stdin);
     8     freopen("disk.out","w",stdout);
     9     while(scanf("%d",&n)!=EOF){
    10         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    11         for(int i=n;i>0;i--){
    12             if(!bs||b[bs]<a[i]) b[++bs]=a[i];
    13             else while(bs&&b[bs]>a[i]) c[++cs]=b[bs--];
    14         }
    15         while(bs) c[++cs]=b[bs--];
    16         for(bs=2;bs<=n;bs++) if(c[bs]>c[bs-1]) break;
    17         if(bs>n) puts("Y");
    18         else puts("J");
    19         bs=cs=0;
    20         memset(b,0,sizeof(b));
    21         memset(c,0,sizeof(c));
    22     }
    23     return 0;
    24 }

    lazy的不想优化逻辑,时间十分充足了。

    四轮车

    【题目描述】

    在地图上散落着 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

    思路

    枚举两个点确定图形各个点的位置;

    对于地图上某个位置有多少车轮可以用map存;

    题解给出的是hash坐标;

    代码实现

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define maxn 10010
     6 using namespace std;
     7 int n,ans[maxn],x1,x2,x3,x4,y1,y2,y3,y4,xx[maxn],yy[maxn],p1,p2;
     8 struct node{int x,y;}P[maxn];
     9 int cmp(const node &a,const node &b){return a.x<b.x;}
    10 int Abs(int a){return a<0?-a:a;}
    11 void Add(){
    12     ans[1]++;
    13     for(int i=1;i<=ans[0];i++) if(ans[i]>9) ans[i]%=10,ans[i+1]++;
    14     if(ans[ans[0]+1])ans[0]++;
    15 }
    16 void Cal(int i,int j){
    17     x1=xx[i],y1=yy[i],x2=xx[j],y2=yy[j];
    18     int a=Abs(y1-y2),b=Abs(x1-x2);
    19     int c=Abs(a-b);
    20     if(c%2) x3=x4=y3=y4=0;
    21     else{
    22         c>>=1;
    23         if(a<b) x3=x1+c,y3=y2+c,x4=x2-c,y4=y1-c;
    24         else x3=x1-c,y3=y2-c,x4=x2+c,y4=y1+c;
    25     }
    26 }
    27 bool Judge(){
    28     if(!x3&&!x4&&!y3&&!y4)return 0;
    29     int falg=0,flag=0;
    30     p1=lower_bound(xx+1,xx+1+n,x3)-xx;
    31     p2=upper_bound(xx+1,xx+1+n,x3)-xx;
    32     for(int i=p1;i<p2;i++){
    33         if(xx[i]!=x3) return 0;
    34         if(yy[i]==y3){falg=1;break;}
    35     }
    36     p1=lower_bound(xx+1,xx+1+n,x4)-xx;
    37     p2=upper_bound(xx+1,xx+1+n,x4)-xx;
    38     for(int i=p1;i<p2;i++){
    39         if(xx[i]!=x4) return 0;
    40         if(yy[i]==y4){flag=1;break;}
    41     }
    42     return falg&&flag;
    43 }
    44 int main(){
    45     freopen("car.in","r",stdin);
    46     freopen("car.out","w",stdout);
    47     scanf("%d",&n),ans[0]=1;
    48     for(int i=1;i<=n;i++) scanf("%d%d",&P[i].x,&P[i].y);
    49     sort(P+1,P+1+n,cmp);
    50     for(int i=1;i<=n;i++) xx[i]=P[i].x,yy[i]=P[i].y;
    51     for(int i=1;i<=n;i++)
    52     for(int j=i+1;j<=n;j++){
    53         if(yy[i]>=yy[j])continue;
    54         Cal(i,j);
    55         if(Judge()) Add();
    56     }
    57     for(int i=ans[0];i>=1;i--) printf("%d",ans[i]);
    58     return 0;
    59 }

     再次感谢峰峰学长!

    点名

    【题目描述】

    在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 < 232

    思路

    splay裸题,好吧我splay卡常数了;//好吧,我没过是因为没有离散化。。。这道题有写离散化,Spoj 10628. Count on a tree。

    也可以用主席树来做,能过;

    正解好像是双堆;

    !int∈[-231,231]

    代码实现

     1 #include<cstdio>
     2 const long long maxn=3e5+10;
     3 long long n,m,a,b;
     4 long long ss[maxn];
     5 long long rt,hd;
     6 long long t[maxn],f[maxn],sz[maxn],am[maxn],s[maxn][2];
     7 void rot(long long x){
     8     long long y=f[x],z=f[y],l,r;
     9     l=s[y][0]==x?0:1,r=l^1;
    10     if(y==rt) rt=x;
    11     else{
    12         if(s[z][0]==y) s[z][0]=x;
    13         else s[z][1]=x;
    14     }
    15     f[x]=z,f[y]=x,f[s[x][r]]=y;
    16     s[y][l]=s[x][r],s[x][r]=y;
    17     sz[y]=sz[s[y][0]]+sz[s[y][1]]+am[y];
    18     sz[x]=sz[s[x][0]]+sz[s[x][1]]+am[x];
    19 }
    20 void splay(long long x){while(x!=rt) rot(x);}
    21 void ins(long long k,long long x,long long fa){
    22     if(!rt){rt=++hd,t[rt]=x,sz[rt]=1,am[rt]++;return;}
    23     while(k) fa=k,++sz[k],k=s[k][x>t[k]];
    24     k=s[fa][x>t[fa]]=++hd;
    25     t[k]=x,sz[k]=1,f[k]=fa,am[k]++;
    26     splay(k);
    27 }
    28 long long find2(long long k,long long x){
    29     if(x<=sz[s[k][0]]) return find2(s[k][0],x);
    30     if(x==sz[s[k][0]]+1) return t[k];
    31     return find2(s[k][1],x-sz[s[k][0]]-1);
    32 }
    33 char r_w[30],r_l;
    34 long long read(long long &x){
    35     while(r_w[0]=getchar(),r_w[0]<'0'||r_w[0]>'9');r_l=1,x=0;
    36     while(r_w[r_l]=getchar(),r_w[r_l]>='0'&&r_w[r_l]<='9') r_l++;
    37      for(long long i=0;i<r_l;i++) x=x*10+r_w[i]-'0';
    38 }
    39 void write(long long x){
    40     if(!x) return;
    41     write(x/10);
    42     putchar(x%10+'0');
    43 }
    44 int main(){
    45     freopen("rollcall.in","r",stdin);
    46     freopen("rollcall.out","w",stdout);
    47     read(n),read(m);
    48     for(long long i=1;i<=n;i++) read(ss[i]);
    49     ins(rt,ss[1],0);
    50     for(long long i=1,j=1;i<=m;i++){
    51         read(a);
    52         while(j<a) ins(rt,ss[++j],0);
    53         
    54         b=find2(rt,i);
    55         if(b) write(b);
    56         else putchar('0');
    57         putchar('
    ');
    58     }
    59     return 0;
    60 }
  • 相关阅读:
    移动Web框架:jQuery Mobile VS Sencha Touch
    2011最具争议性文章:中国网页设计为什么这么烂?
    如何学习嵌入式linux[转]
    嵌入式linux,老手给新手的建议
    开发菜鸟应该知道的十件事
    C#中二进制、八进制、十六进制和十进制之间的相互转化问题
    使用splitter控件 将界面分成可以调整宽度的三个部分
    Mutex 类
    Java 发邮件
    Java Servlet介绍 2
  • 原文地址:https://www.cnblogs.com/J-william/p/6985391.html
Copyright © 2011-2022 走看看