zoukankan      html  css  js  c++  java
  • 海亮游记DAY3

    我。。。

    自闭了。。。

    今天按照惯例依旧。。。考试了

    被昨天的题目暴虐以及被一些题目摁在地上摩擦之后,

    我又一次的坐在了机房,拿起了键盘和鼠标玩起了小恐龙,嗯,真   香

    好了,先来看一下今天的毒瘤题目:
    2019/7/8
    一、 题目概览
    中文题目名称 三笔画 取石子 放积木
    英文题目名称 3lines stone block
    可执行文件名 3lines stone block
    输入文件名 3lines.in stone.in block.in
    输出文件名 3lines.out stone.out block.out
    时间限制 1s 1s 1
    空间限制 256MB 256MB 256MB
    测试点数目 捆绑测试 捆绑测试 10
    测试点分值 捆绑测试 捆绑测试 10
    题目类型 传统 传统 传统
    比较方式 全文比较 全文比较 全文比较
    是否有部分分 否 否 否
    二、注意事项:
    1.文件名(程序名和输入输出文件名)必须使用小写。
    2.C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须0。
    3.开启 O2 优化,栈空间开大至 256M。
    三笔画( 3lines)
    【 题目描述】
    二维平面内有 n 个不同的点, Alice 需要在平面内画至多 3 条直线使得所有点在直线上。
    问: Alice 能否完成任务, 如果能, 输出”YES”; 否则, 输出”NO”。
    注意: 由于 Alice 的画图水平有限, 直线只能平行于坐标轴。
    【输入数据】
    第一行, 一个整数 n。
    接下来 n 行, 第 i+1 行包含空格隔开的整数 xi,yi,表示第 i 个点的坐标。
    【输出数据】
    若 Alice 能完成任务, 输出”YES”, 否则输出”NO”。
    【 样例输入】
    6
    1 7
    0 0
    1 2
    2 0
    1 4
    3 4
    【样例输出】
    YES
    【样例解释】
    三条直线分别为 x=1,y=0,y=4。
    【数据范围】
    对于 30%的数据, 1 <= n <= 13。
    对于 60%的数据, 1 <= n <= 20。
    对于 100%的数据, 1 <= n <= 5e4, 0 <= xi, yi <= 1e9。
    取石子( stone)
    【题目描述】
    有 n 堆石子,第 i 堆有 xi 个。
    Alice 和 Bob 轮流取石子(先后手未定), Alice 每次从一堆中取走 a 个, Bob 每次从一
    堆中取走 b 个,无法操作者输。
    不难发现只会有四种情况: Alice 必胜; Bob 必胜;先手必胜;后手必胜。
    你需要选定若干堆石子(共有 2^n 种方案), Alice 和 Bob 只能在你选出的堆中取,问
    以上四种情况对应的方案数。对 10^9+7 取模。
    【输入数据】
    第一行三个整数 n,a,b,第二行 n 个整数 x1~xn。
    【输出数据】
    一行四个整数,分别表示 Alice 必胜、 Bob 必胜、先手必胜和后手必胜的方案数,对
    10^9+7 取模。
    【样例输入】
    2 2 3
    2 3
    【样例输出】
    2 0 1 1
    【样例解释】
    选定空集时后手必胜, 选定{2}时 Alice 必胜, 选定{3}时先手必胜, 选定{2,3}时 Alice 必胜。
    【数据范围】
    对于 10%的数据, n, xi <= 5。
    对于 50%的数据, n <= 20。
    对于另外 10%的数据, a = b。
    对于又另外 20%的数据, a = 1。
    对于 100%的数据, 1 <= n <= 1e5, 1 <= a, b, xi <= 1e9。
    放积木(block)
    【问题描述】
    Alice 有 n 块积木,放置第 i 块积木会占据区间[Li, Ri]。
    Alice 每次会腾出一个区间放积木,她希望放的积木尽可能多,对每个询问区间,你需
    要回答 Alice 最多可放置的积木数量。
    注意: 积木与积木的放置区间不可重叠,且任意选定的积木放置区间不能超出询问区间。
    【输入格式】
    第一行三个整数 n,q,len,表示积木的数量,询问数和 len 的大小(数据保证 1≤Li,Ri≤
    len) 。
    接下来 n 行,每行两个整数 Li,Ri, 表示积木占据的区间。
    接下来 q 行,每行两个整数 ai,bi, 表示询问区间。
    【输出格式】
    对于每组询问输出对应的答案。
    【输入样例】
    3 2 4
    1 2
    2 3
    3 4
    1 3
    3 3

    T1:

    说实话,这道题,真的只是一道模拟题(我最近对模拟有点上火,所以我要模拟退下火,,,

    因为只有3条边,而且只有x,y两条边,所以就算码量最大的纯模拟也只有8种情况

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 template <typename type>
      4 void scan(type &x){
      5     type f=1;x=0;char s=getchar();
      6     while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
      7     while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
      8     x*=f;
      9 }
     10 const int maxn=5e4+7;
     11 struct node{
     12     int x,y;
     13 }a[50007];
     14 int n;
     15 map<int,int>xx;
     16 map<int,int>yy;
     17 //map<int,int>visx;
     18 //map<int,int>visy;
     19 int maxx1,maxx2,k1,k2;
     20 //int mx,my;
     21 int main(){
     22     freopen("3lines.in","r",stdin);
     23     freopen("3lines.out","w",stdout);
     24     scan(n);
     25     for(int i=1;i<=n;i++){
     26         scan(a[i].x);
     27         xx[a[i].x]++;
     28         if(maxx1<xx[a[i].x]){
     29             k1=a[i].x;
     30             maxx1=xx[a[i].x];
     31         }
     32 //        mx=max(mx,a[i].x);
     33         scan(a[i].y);
     34         yy[a[i].y]++;
     35         if(maxx2<yy[a[i].y]){
     36             k2=a[i].y;
     37             maxx2=yy[a[i].y];
     38         }
     39 //        my=max(my,a[i].y);
     40     }
     41     if(maxx1>maxx2){
     42         for(int i=1;i<=n;i++){
     43             if(a[i].x==k1){
     44                 yy[a[i].y]--;
     45                 xx[a[i].x]--;
     46             }
     47         }//加第一条边 x
     48         maxx1=0,maxx2=0;
     49         for(int i=1;i<=n;i++){
     50 //            if(visx[a[i].x]==0){
     51                 if(maxx1<xx[a[i].x]){
     52                     maxx1=xx[a[i].x];
     53                     k1=a[i].x;
     54                 }
     55 //                visx[a[i].x]++;
     56 //            }
     57 //            if(visy[a[i].y]==0){
     58                 if(maxx2<yy[a[i].y]){
     59                     maxx2=yy[a[i].y];
     60                     k2=a[i].y;
     61                 }
     62 //                visy[a[i].y]++;
     63 //            }
     64         }
     65         if(maxx1==0||maxx2==0){printf("YES");return 0;}//x
     66         if(maxx1>maxx2){
     67         for(int i=1;i<=n;i++){
     68             if(a[i].x==k1){
     69                 yy[a[i].y]--;
     70                 xx[a[i].x]--;
     71             }
     72         }//加第2条边 x
     73         maxx1=0,maxx2=0;
     74         for(int i=1;i<=n;i++){
     75 //            if(visx[a[i].x]==1){
     76                 if(maxx1<xx[a[i].x]){
     77                     maxx1=xx[a[i].x];
     78                     k1=a[i].x;
     79                 }
     80 //                visx[a[i].x]++;
     81 //            }
     82 //            if(visy[a[i].y]==1){
     83                 if(maxx2<yy[a[i].y]){
     84                     maxx2=yy[a[i].y];
     85                     k2=a[i].y;
     86                 }
     87 //                visy[a[i].y]++;
     88 //            }
     89         }
     90         if(maxx1==0||maxx2==0){printf("YES");return 0;}//xx
     91         if(maxx1>maxx2){
     92         for(int i=1;i<=n;i++){
     93             if(a[i].x==k1){
     94                 yy[a[i].y]--;
     95                 xx[a[i].x]--;
     96             }
     97         }//加第3条边x 
     98         for(int i=1;i<=n;i++){
     99             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
    100         }
    101         printf("YES");return 0;//xxx
    102     }else
    103     {
    104         for(int i=1;i<=n;i++){
    105             if(a[i].y==k2){
    106                 xx[a[i].x]--;
    107                 yy[a[i].y]--;
    108             }
    109         }//3y
    110         for(int i=1;i<=n;i++){
    111             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
    112         }
    113         printf("YES");return 0;//xxy
    114     }
    115     }else{
    116         for(int i=1;i<=n;i++){
    117             if(a[i].y==k2){
    118                 xx[a[i].x]--;
    119                 yy[a[i].y]--;
    120             }
    121         }//2y
    122         maxx1=0,maxx2=0;
    123         for(int i=1;i<=n;i++){
    124 //            if(visx[a[i].x]==1){
    125                 if(maxx1<xx[a[i].x]){
    126                     maxx1=xx[a[i].x];
    127                     k1=a[i].x;
    128                 }
    129 //                visx[a[i].x]++;
    130 //            }
    131 //            if(visy[a[i].y]==1){
    132                 if(maxx2<yy[a[i].y]){
    133                     maxx2=yy[a[i].y];
    134                     k2=a[i].y;
    135                 }
    136 //                visy[a[i].y]++;
    137 //            }
    138         }
    139         if(maxx1==0||maxx2==0){printf("YES");return 0;}//xy
    140         if(maxx1>maxx2){
    141         for(int i=1;i<=n;i++){
    142             if(a[i].x==k1){
    143                 yy[a[i].y]--;
    144                 xx[a[i].x]--;
    145             }
    146         }
    147         for(int i=1;i<=n;i++){
    148             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
    149         }
    150         printf("YES");return 0;//xyx
    151     }else{
    152         for(int i=1;i<=n;i++){
    153             if(a[i].y==k2){
    154                 xx[a[i].x]--;
    155                 yy[a[i].y]--;
    156             }
    157         }//3y
    158         for(int i=1;i<=n;i++){
    159             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
    160         }
    161         printf("YES");return 0;//xyy
    162     }
    163     }}else{
    164         for(int i=1;i<=n;i++){
    165             if(a[i].y==k2){
    166                 xx[a[i].x]--;
    167                 yy[a[i].y]--;
    168             }
    169         }//1y
    170         maxx1=0,maxx2=0;
    171         for(int i=1;i<=n;i++){
    172 //            if(visx[a[i].x]==0){
    173                 if(maxx1<xx[a[i].x]){
    174                     maxx1=xx[a[i].x];
    175                     k1=a[i].x;
    176                 }
    177 //                visx[a[i].x]++;
    178 //            }
    179 //            if(visy[a[i].y]==0){
    180                 if(maxx2<yy[a[i].y]){
    181                     maxx2=yy[a[i].y];
    182                     k2=a[i].y;
    183                 }
    184 //                visy[a[i].y]++;
    185 //            }
    186         }
    187         if(maxx1==0||maxx2==0){printf("YES");return 0;}//y
    188         if(maxx1>maxx2){
    189             for(int i=1;i<=n;i++){
    190             if(a[i].x==k1){
    191                 yy[a[i].y]--;
    192                 xx[a[i].x]--;
    193             }
    194         }//加第2条边 x
    195         maxx1=0,maxx2=0;
    196         for(int i=1;i<=n;i++){
    197 //            if(visx[a[i].x]==1){
    198                 if(maxx1<xx[a[i].x]){
    199                     maxx1=xx[a[i].x];
    200                     k1=a[i].x;
    201                 }
    202 //                visx[a[i].x]++;
    203 //            }
    204 //            if(visy[a[i].y]==1){
    205                 if(maxx2<yy[a[i].y]){
    206                     maxx2=yy[a[i].y];
    207                     k2=a[i].y;
    208                 }
    209 //                visy[a[i].y]++;
    210 //            }
    211         }
    212         if(maxx1==0||maxx2==0){printf("YES");return 0;}//yx
    213         if(maxx1>maxx2){
    214             for(int i=1;i<=n;i++){
    215             if(a[i].x==k1){
    216                 yy[a[i].y]--;
    217                 xx[a[i].x]--;
    218             }
    219         }//加第3条边x 
    220         for(int i=1;i<=n;i++){
    221             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
    222         }
    223         printf("YES");return 0;//yxx
    224         }else{
    225             for(int i=1;i<=n;i++){
    226             if(a[i].y==k2){
    227                 xx[a[i].x]--;
    228                 yy[a[i].y]--;
    229             }
    230         }//3y
    231         for(int i=1;i<=n;i++){
    232             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
    233         }
    234         printf("YES");return 0;//yxy
    235         }
    236         }else{
    237             for(int i=1;i<=n;i++){
    238             if(a[i].y==k2){
    239                 xx[a[i].x]--;
    240                 yy[a[i].y]--;
    241             }
    242         }//2y
    243         maxx1=0,maxx2=0;
    244         for(int i=1;i<=n;i++){
    245 //            if(visx[a[i].x]==1){
    246                 if(maxx1<xx[a[i].x]){
    247                     maxx1=xx[a[i].x];
    248                     k1=a[i].x;
    249                 }
    250 //                visx[a[i].x]++;
    251 //            }
    252 //            if(visy[a[i].y]==1){
    253                 if(maxx2<yy[a[i].y]){
    254                     maxx2=yy[a[i].y];
    255                     k2=a[i].y;
    256                 }
    257 //                visy[a[i].y]++;
    258 //            }
    259         }
    260         if(maxx1==0||maxx2==0){printf("YES");return 0;}//yy
    261         if(maxx1>maxx2){
    262             for(int i=1;i<=n;i++){
    263             if(a[i].x==k1){
    264                 yy[a[i].y]--;
    265                 xx[a[i].x]--;
    266             }
    267         }//加第3条边x 
    268         for(int i=1;i<=n;i++){
    269             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
    270         }
    271         printf("YES");return 0;//yyx
    272         }else{
    273             for(int i=1;i<=n;i++){
    274             if(a[i].y==k2){
    275                 xx[a[i].x]--;
    276                 yy[a[i].y]--;
    277             }
    278         }//3y
    279         for(int i=1;i<=n;i++){
    280             if(xx[a[i].x]>0||yy[a[i].y]>0){printf("NO");return 0;}
    281         }
    282         printf("YES");return 0;//yyy
    283         }
    284         }
    285     }
    286 
    287     return 0;
    288 }
    我的288行暴力代码qwq

    对于正解来说,就是将有些不必要的情况去掉,

    考虑这三条直线的状态,只可能为
    (1)三条水平线
    (2)两条水平线+一条垂直线
    (剩余情况交换 x,y 坐标即可)
    我们用一个数组统计同一 y 坐标上有几个点。
    对于 1)的情况,只需判断是否只有三个及以下的 y 坐标上有点即可。
    对于 2)的情况,可以枚举垂直线的 x 坐标,将这条垂直线上的点全部删去,判断剩下的
    点的 y 坐标是否只有两种及以下。
    将点按 x 坐标排序后即可做到 O(n)的扫描。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 int n;
     6 struct point{
     7     int x,y;
     8 }a[50001];
     9 int xx[50001];
    10 int yy[50001];
    11 int sum[50001];
    12 int fx,fy;
    13 int read(){
    14     scanf("%d",&n);
    15     for (int i=1;i<=n;++i){
    16         scanf("%d%d",&xx[i],&yy[i]);
    17         a[i].x=xx[i];
    18         a[i].y=yy[i];        
    19     }   
    20     sort(xx+1,xx+n+1);
    21     sort(yy+1,yy+n+1);
    22     fx=unique(xx+1,xx+n+1)-xx-1;
    23     fy=unique(yy+1,yy+n+1)-yy-1;
    24     for (int i=1;i<=n;++i){
    25         a[i].x=lower_bound(xx+1,xx+fx+1,a[i].x)-xx;
    26         a[i].y=lower_bound(yy+1,yy+fy+1,a[i].y)-yy;
    27     }
    28 }
    29 int cmp(const point &a,const point &b){
    30     return a.x<b.x?1:((a.x==b.x)&&(a.y<b.y));
    31 }
    32 int work(){
    33     int tot=0;
    34     sort(a+1,a+n+1,cmp);    
    35     for (int i=1;i<=n;++i)
    36         if (sum[a[i].y]++==0)++tot;
    37     if (tot<=3)return 1;
    38     int t=1,w;
    39     while (t<=n){
    40         w=t;
    41         while (w<n&&a[w+1].x==a[t].x)++w;
    42         for (int i=t;i<=w;++i)
    43             if (sum[a[i].y]--==1)--tot;
    44         if (tot<=2)return true;
    45         for (int i=t;i<=w;++i)
    46             if (sum[a[i].y]++==0)++tot;
    47         t=w+1;
    48     }
    49     return 0;
    50 }
    51 int main(){
    52     freopen("3lines.in","r",stdin);
    53     freopen("3lines.out","w",stdout);
    54     read();
    55     if (work()){
    56         puts("YES");
    57     }
    58     else {
    59         memset(sum,0,sizeof(sum));
    60         for (int i=1;i<=n;++i)
    61             swap(a[i].x,a[i].y);
    62         puts(work()? "YES" : "NO");
    63     }
    64     fclose(stdin);
    65     fclose(stdout);
    66 }
    std

    T2:

    是一道博弈论,但是我没有学过啊QWQ,但是在情况的讨论中还是十分清晰。

    下面为分析过程:
    不妨假设a < b。
    每堆石子先对a + b取模,然后可以分为4种:
    (1)xi < a,没用。
    (2)a <= xi < b,只要存在则a必胜。
    (3)b <= xi < 2a,只和奇偶性有关。
    (4)2a <= xi, 存在至少2个则a必胜, 存在1个且(3)为偶数则先手必胜, 存在1个且(3)为奇
    数则a必胜, 不存在且(3)为奇数则先手必胜, 不存在且(3)为偶数则后手必胜。
    时间复杂度 O(n)

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 typedef long long ll;
     5 inline int Get() {
     6     char ch;
     7     while ((ch = getchar()) < '0' || ch > '9');
     8     int Num = ch - '0';
     9     while ((ch = getchar()) >= '0' && ch <= '9')
    10         Num = (Num << 3) + (Num << 1) + ch - '0';
    11     return Num;
    12 }
    13 const int Mod = 1e9 + 7;
    14 const int N = 1e5 + 5;
    15 int n, A, B, x[N], n1, n2, n3, n4, former, latter, mner, g[N][2];
    16 inline int pow(int x, int k) {
    17     ll res = 1, r = x;
    18     for (; k; k >>= 1, r = r * r % Mod)
    19         if (k & 1) res = res * r % Mod;
    20     return res;
    21 }
    22 int main() {
    23     freopen("stone.in", "r", stdin);
    24     freopen("stone.out", "w", stdout);
    25     n = Get(), A = Get(), B = Get();
    26     for (int i = 1; i <= n; ++i) x[i] = Get();
    27     
    28     if (A == B) {
    29         for (int i = 1; i <= n; ++i) x[i] /= A;
    30         
    31         g[0][0] = 1;
    32         for (int i = 1; i <= n; ++i) {
    33             int c = x[i] & 1;
    34             g[i][0] = (g[i - 1][0] + g[i - 1][c ^ 0]) % Mod;
    35             g[i][1] = (g[i - 1][1] + g[i - 1][c ^ 1]) % Mod;
    36         }
    37         
    38         printf("0 0 %d %d
    ", g[n][1], g[n][0]);
    39         return 0;
    40     }
    41     
    42     for (int i = 1; i <= n; ++i) x[i] %= (A + B);
    43     int mn = std :: min(A, B), mx = std :: max(A, B);
    44     
    45     for (int i = 1; i <= n; ++i) 
    46         n1 += (x[i] < mn), n2 += (mn <= x[i] && x[i] < mx), n3 += (mx <= x[i] && x[i] < 2 * mn), n4 += (2 * mn <= x[i] && mx <= x[i]);    
    47     
    48     mner = (ll)(pow(2, n2) - 1) * pow(2, n1 + n3 + n4) % Mod;
    49     if (mner < 0) mner += Mod;
    50     
    51     g[0][0] = 1;
    52     for (int i = 1; i <= n3; ++i) {
    53         g[i][0] = (g[i - 1][0] + g[i - 1][1]) % Mod;
    54         g[i][1] = (g[i - 1][1] + g[i - 1][0]) % Mod;
    55     }
    56     
    57     former = (ll)pow(2, n1) * g[n3][1] % Mod;
    58     latter = (ll)pow(2, n1) * g[n3][0] % Mod;
    59     
    60     int total1 = n4, total2 = pow(2, n4) - n4 - 1;
    61     if (total2 < 0) total2 += Mod;
    62     
    63     mner = ((ll)total2 * pow(2, n1 + n3) % Mod + (ll)total1 * pow(2, n1) % Mod * g[n3][1] % Mod + mner) % Mod;
    64     former = ((ll)total1 * pow(2, n1) % Mod * g[n3][0] % Mod + former) % Mod; 
    65     if (A < B) printf("%d 0 %d %d
    ", mner, former, latter);
    66     else printf("0 %d %d %d
    ", mner, former, latter);
    67     fclose(stdin);
    68     fclose(stdout);
    69     return 0;
    70 }
    std

    T3:

    其实这道题与我们昨天讲到的一道题十分相似(CF1175E Minimal Segment Cover),但是因为时间原因所以没有写,然后自己写的贪心暴力还写挂了。。。

     1 #include<cstdio>
     2 int N,Q,len;
     3 int f[100010][20];
     4 int min(int a,int b){
     5     return a<b?a:b;
     6 }
     7 int read(){
     8     scanf("%d%d%d",&N,&Q,&len);
     9     for (int i=1;i<=len+2;++i)
    10         for (int j=0;j<=16;++j)
    11             f[i][j]=len+1;
    12 
    13     for (int i=1;i<=N;++i){
    14         int a,b;
    15         scanf("%d%d",&a,&b);
    16         f[a][0]=min(f[a][0],b);
    17     }
    18 }
    19 int work(){
    20     for (int i=len+1;i>=1;--i)
    21         f[i][0]=min(f[i][0],f[i+1][0]);
    22     for (int j=1;j<=16;++j)
    23        for (int i=len;i>=1;--i)
    24            f[i][j]=min(f[i+1][j],f[f[i][j-1]+1][j-1]);
    25 }
    26 int ff(int a,int b){
    27     int ans=0;
    28     for (int i=16;i>=0;--i)
    29         if (f[a][i]<=b){
    30             ans+=1<<i;
    31             a=f[a][i]+1;
    32         }
    33     return ans;
    34 }
    35 int answer(){
    36     for (int i=1;i<=Q;++i){
    37         int a,b;
    38         scanf("%d%d",&a,&b);
    39         printf("%d
    ",ff(a,b));
    40     } 
    41 }
    42 int main(){
    43     freopen("block.in","r",stdin);
    44     freopen("block.out","w",stdout);
    45     read();
    46     work();
    47     answer();    
    48     fclose(stdin);
    49     fclose(stdout);
    50 } 
    std
  • 相关阅读:
    Oracle的分区打点
    学习Struts2经验总结
    优化MVC,实现数据库表的记录的添加、删除、修改、查询。
    基于struts研究传值问题
    基于“MVC”框架集设计模式,开发用户管理系统!
    使用Struts,实现简单的登录
    QT学习4:使用窗口部件
    QT学习9:绘制函数
    QT学习8:准备战斗
    QT学习6:组装丰富的积木!
  • 原文地址:https://www.cnblogs.com/xishirujin/p/11153995.html
Copyright © 2011-2022 走看看