zoukankan      html  css  js  c++  java
  • 2018.09.15模拟总结(T1,T3)

    过了一周,终于迎来了第二次模拟(这不是期待的语气),看第一周毒瘤程度,我就觉得接下来的模拟只能更毒瘤。

     

    花了10多分钟读完了三道题,觉得暴力还是挺好写的,然后在每一道题都思索那么几分钟后,觉得还是写暴力靠谱一些……不过还好,一个半点就把暴力都写完了。

    然后我就接着想正解……

    T1 game

      这道题刚开始就觉得是二维线段树,然后瞟了一眼数据范围:1e6 * 1e6,于是就犹豫了。就一直在想能不能行和列各只开一个线段树,最终反正是没想出来,于是开始优化我的暴力。推了半天发现了一个惊天秘密:就是修改的顺序是可以颠倒的:于是我就先O(n)处理了所有行的修改,然后对于所有列的修改,再暴力的O(n2)修改:所以说,只要这个数据行的修改越多,我就越容易拿掉80的点……后来经过【地表最强】lsy的山寨数据测了一下,发现还是稳稳的40分……

      暴力以及考场心路历程就说到这吧,该讲讲正解是啥咧。

      嗯……概括一下,就是这题没A就是数列没学好。

      我们开一个lzy_rol[n], lzy_lin[m]两个标记数组,记录每一行或是每一列要乘上多少。假设我们没有列的操作,那么一列看成一个数,整张图就是一个长度为m的等差数列,不想O(1)的话O(m)就能求出来。现在加上了列的操作。其实就是对于每一个数ai乘上了一个lzy_lin[i],只要按顺序算到ai,然后答案加上ai * lzy_lin[i]就行了…………

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter puts("") 
    13 #define space putchar(' ')
    14 #define Mem(a, x) memset(a, x, sizeof(a))
    15 #define rg register
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const db eps = 1e-8;
    20 const ll mod = 1e9 + 7;
    21 const int maxn = 1e6 + 5;
    22 inline ll read()
    23 {
    24     ll ans = 0;
    25     char ch = getchar(), last = ' ';
    26     while(!isdigit(ch)) {last = ch; ch = getchar();}
    27     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
    28     if(last == '-') ans = -ans;
    29     return ans;
    30 }
    31 inline void write(ll x)
    32 {
    33     if(x < 0) x = -x, putchar('-');
    34     if(x >= 10) write(x / 10);
    35     putchar(x % 10 + '0');
    36 }
    37 
    38 int n, m, q; 
    39 char c[5];
    40 ll lzy_rol[maxn], lzy_lin[maxn]; 
    41 ll s = 0, d = 0, sum = 0;
    42 
    43 ll getnum(int x, int i)
    44 {
    45     return ((ll)(i - 1) * m + x) % mod;
    46 }
    47 
    48 int main()
    49 {
    50     freopen("game.in", "r", stdin);
    51     freopen("game.out", "w", stdout);
    52     n = read(); m = read(); q = read();
    53     for(int i = 1; i < maxn; ++i) lzy_rol[i] = lzy_lin[i] = 1;
    54     for(int i = 1; i <= q; ++i)
    55     {
    56         scanf("%s", c); int x = read(); ll k = read();
    57         if(c[0] == 'R') lzy_rol[x] *= k, lzy_rol[x] %= mod;    
    58         else lzy_lin[x] *= k, lzy_lin[x] %= mod;
    59     }
    60     for(int i = 1; i <= n; ++i)
    61     {
    62         s += getnum(1, i) * lzy_rol[i]; s %= mod;
    63         d += lzy_rol[i]; d %= mod;
    64     }                            //s:首项,d:公差 
    65     for(rg int i = 1; i <= m; ++i)        
    66     {
    67         sum += lzy_lin[i] * s; sum %= mod;
    68         s += d; s %= mod;
    69     }
    70     write(sum); enter;
    71     return 0;
    72 }
    View Code

    T2 jump

      在考场上我第一反应就是20分暴力,然后chuachuachua15分钟就写完了。于是就直接去搞第三题的暴力了。

      第三题暴力写完后又回来看这道题,然后就想到了一个50分的想法:先求出一个跳房子的周期,然后移动每一次k步,只要对周期取模即可。至于修改,那就是暴利修改啦。然而时间不是很够,于是就没写完。

      至于正解,我到现在还不是很懂。学姐写的是线段树维护置换。然后正解是一个很奇特的算法,不过这俩都没听懂……据说路由器还有一个更简单的做法,然而没人跟我讲啊……

    T3 sequence

      我上文已经说过了,当时也是写的暴利。而且还没想到比较正常的O(n2)暴利,自己搞了一个很奇葩的算法:就是先预处理每一个数出现的位置,然后统计当前查询区间没出现的数,然后利用这些数字不断扩大查询区间,直到区间最大值减最小值等于区间长度为止。

      正解其实跟我的暴利有点像:要维护两个线段树:第一个是区间最值,第二个是在值域区间中出现位置的最值(所以说,RMQ其实就行了,而且常数更小)。

      然后我们要递归的查询:先在询问区间[L, R]中查询最小最大值Min, Max.然后在第二个线段树的区间[Min, Max]中查询出现位置的最值Minl, Minr,再换到第一个线段树在[Minl, Minr]中查询数的最大最小值……直到Max - Min = R - L,这时候的L, R 就是答案。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 1e5 + 5;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     27     if(last == '-') ans = -ans;
     28     return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32     if(x < 0) x = -x, putchar('-');
     33     if(x >= 10) write(x / 10);
     34     putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m, a[maxn];
     38 
     39 struct Tree
     40 {
     41     int a[maxn];
     42     int l[maxn << 2], r[maxn << 2], Min[maxn << 2], Max[maxn << 2];
     43     Tree()
     44     {
     45         Mem(a, 0);
     46         Mem(l, 0); Mem(r, 0);
     47         Mem(Min, 0); Mem(Max, 0);
     48     }
     49     void build(int L, int R, int now)
     50     {
     51         l[now] = L; r[now] = R;
     52         if(L == R) {Min[now] = Max[now] = a[L]; return;}
     53         int mid = (L + R) >> 1;
     54         build(L, mid, now << 1);
     55         build(mid + 1, R, now << 1 | 1);
     56         Min[now] = min(Min[now << 1], Min[now << 1 | 1]);
     57         Max[now] = max(Max[now << 1], Max[now << 1 | 1]);        
     58     }
     59     int query(int L, int R, int now, bool flg)
     60     {
     61         if(L == l[now] && R == r[now]) return flg ? Max[now] : Min[now];
     62         int mid = (l[now] + r[now]) >> 1;
     63         if(R <= mid) return query(L, R, now << 1, flg);
     64         else if(L > mid) return query(L, R, now << 1 | 1, flg);
     65         else 
     66         {
     67             int ret;
     68             if(flg) ret = max(query(L, mid, now << 1, flg), query(mid + 1, R, now << 1 | 1, flg));
     69             else ret = min(query(L, mid, now << 1, flg), query(mid + 1, R, now << 1 | 1, flg));
     70             return ret;
     71         }
     72     }
     73 }Seq, Num;
     74 
     75 #define pr pair<int, int>
     76 #define mp make_pair 
     77 #define fir first
     78 #define sec second
     79 pr Query(int L, int R)
     80 {
     81     while(1)
     82     {
     83         int Ml = Seq.query(L, R, 1, 0), Mr = Seq.query(L, R, 1, 1);
     84         if(Mr - Ml == R - L) return mp(L, R);
     85         L = Num.query(Ml, Mr, 1, 0);
     86         R = Num.query(Ml, Mr, 1, 1);
     87     }
     88 }
     89 
     90 int main()
     91 {
     92     freopen("sequence.in", "r", stdin);
     93     freopen("sequence.out", "w", stdout);
     94     n = read();
     95     for(int i = 1; i <= n; ++i) a[i] = read();
     96     for(int i = 1; i <= n; ++i) Seq.a[i] = a[i], Num.a[a[i]] = i;
     97     Seq.build(1, n, 1); Num.build(1, n, 1); 
     98     m = read();
     99     for(int i = 1; i <= m; ++i)
    100     {
    101         int L = read(), R = read();
    102         pr p = Query(L, R);
    103         write(p.fir); space; write(p.sec); enter;
    104     }
    105     return 0;
    106 }
    View Code

    不过这个线段树好像常数很大,然后换了数据后后面几个点就TLE了……那真正的正解就不太懂了。

      总的来说今天的考试还是挺顺利的,暴利一个半点很愉快的就写完了。自己估分100左右,结果出成绩后刚好102,顿时觉得自己相当nb。反正想拿的分都拿到了,就没什么遗憾。

  • 相关阅读:
    JAVA中使用FTPClient上传下载
    js 计算题
    js 中的call apply
    js闭包、原型、继承、作用域
    jQuery中.bind() .live() .delegate() .on()的区别
    Javascript中String、Array常用方法介绍
    常用函数
    事件委托,阻止默认事件
    【探讨】javascript事件机制底层实现原理
    css 垂直水平居中
  • 原文地址:https://www.cnblogs.com/mrclr/p/9651284.html
Copyright © 2011-2022 走看看