zoukankan      html  css  js  c++  java
  • 洛谷比赛『期末考后的休闲比赛2』

    前言(在题解前面瞎扯的话)

      这场比赛已经结束了有几天,但我各种忙,虽然AK但还是没来得及写题解。(我才不会告诉你我跑去学数据结构了)


    T1 区间方差

    (就不贴题好了)

      首先可以推公式(我们可以知道,线段树然而并不能通过初中学过的方差公式在log(L)内求出方差):

    (s2表示方差,L表示区间长度,xi表示区间的每一项,最后一个x上画了一根线表示这些数据的平均数)

    二项式定理完全平方公式可得:

     

    再次展开:

    另外,再代入以下这个

    得到了:

    然后继续吧。。 

    然后duang地一声合并同类项,于是我们得到了:

      然后可以高兴地发现,和 和 平方和都是线段树的拿手好戏,然而按照这么写估计只能过几个点。

    很明显平方和肯定会超long long,难不成还要写一个高精度?

      仔细读读题,然后就发现可以模一个1e9+7。然后处处取模(笑),最后就能够水掉这道水题了。

      至于求逆元,可以用在线算法,扩展欧几里得、快速幂(好像是基于欧拉定理),也可以用线性推逆元预处理所有可能用到的逆元。

    Code(线段树)

      1 /**
      2  * luogu.org
      3  * Problem#2005
      4  * Accepted
      5  * Time:965ms / 691ms
      6  * Memory:18601k / 18601k
      7  */
      8 #include<iostream>
      9 #include<fstream>
     10 #include<sstream>
     11 #include<cstdio>
     12 #include<cstdlib>
     13 #include<cstring>
     14 #include<ctime>
     15 #include<cctype>
     16 #include<cmath>
     17 #include<algorithm>
     18 #include<stack>
     19 #include<queue>
     20 #include<set>
     21 #include<map>
     22 #include<vector>
     23 using namespace std;
     24 typedef bool boolean;
     25 #define smin(a, b)    (a) = min((a), (b))
     26 #define smax(a, b)    (a) = max((a), (b))
     27 template<typename T>
     28 inline void readInteger(T& u){
     29     char x;
     30     int aFlag = 1;
     31     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     32     if(x == -1)    return;
     33     if(x == '-'){
     34         x = getchar();
     35         aFlag = -1;
     36     }
     37     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
     38     ungetc(x, stdin);
     39     u *= aFlag;
     40 }
     41 
     42 const int moder = 1000000007;
     43 
     44 template<typename T1, typename T2>
     45 class Pair{
     46     public:
     47         T1 x;
     48         T2 y;
     49         Pair(T1 x, T2 y):x(x), y(y){    }
     50         Pair operator +(Pair another){
     51             return Pair(x + another.x % moder, y + another.y % moder);
     52         }
     53 };
     54 
     55 typedef class TreeNode{
     56     public:
     57         int sum;
     58         int sum2;
     59         int from, end;
     60         TreeNode* left, *right;
     61         TreeNode(long long sum, int from, int end):from(from), end(end), left(NULL), right(NULL), sum(sum){
     62             sum2 = sum * sum % moder;
     63         }
     64         void pushUp(){
     65             this->sum = this->left->sum + this->right->sum;
     66             this->sum %= moder;
     67             this->sum2 = this->left->sum2 + this->right->sum2;
     68             this->sum2 %= moder;
     69         }
     70 }TreeNode;
     71 
     72 typedef class SegTree{
     73     public:
     74         TreeNode* root;
     75         
     76         SegTree():root(NULL){    }
     77         SegTree(int size, int* val){
     78             build(root, 1, size, val);
     79         }
     80         
     81         void build(TreeNode*& node, int from, int end, int* val){
     82             node = new TreeNode(0, from, end);
     83             if(from == end){
     84                 node->sum = val[from];
     85                 node->sum2 = (int)(val[from] * 1LL * val[from] % moder);
     86                 return;
     87             }
     88             int mid = (from + end) >> 1;
     89             build(node->left, from, mid, val);
     90             build(node->right, mid + 1, end, val);
     91             node->pushUp();
     92         }
     93         
     94         void update(TreeNode*& node, int index, int val){
     95             if(node->from == index && node->end == index){
     96                 node->sum = val;
     97                 node->sum2 = (int)(val * 1LL * val % moder);
     98                 return;
     99             }
    100             int mid = (node->from + node->end) >> 1;   
    101             if(index <= mid)    update(node->left, index, val);
    102             else update(node->right, index, val);
    103             node->pushUp();
    104         }
    105         
    106         Pair<long long, long long> query(TreeNode*& node, int from, int end){
    107             if(node->from == from && node->end == end){
    108                 return Pair<long long, long long>(node->sum, node->sum2);
    109             }
    110             int mid = (node->from + node->end) >> 1;
    111             if(end <= mid)    return query(node->left, from, end);
    112             if(from > mid)    return query(node->right, from, end);
    113             return query(node->left, from, mid) + query(node->right, mid + 1, end);
    114         }
    115         
    116 }SegTree;
    117 
    118 /*
    119 int pow_mod(int x, int pos){
    120     if(pos == 1)    return x;
    121     int temp = pow_mod(x, pos / 2);
    122     if(pos & 1)    return (int)(temp * 1LL * temp % moder * x % moder);
    123     return (int)(temp * 1LL * temp % moder);
    124 }
    125 */
    126 
    127 void gcd(int a, int b, int& d, int& x, int& y){
    128     if(b == 0){
    129         d = a;x = 1;y= 0;
    130     }else{    gcd(b, a % b, d, y, x); y -= x * (a / b);    }
    131 }
    132 
    133 int getInv(int a, int n){
    134     int d, x, y;
    135     gcd(a, n, d, x, y);
    136     return (x + n) % n;
    137 }
    138 
    139 int n, m;
    140 SegTree st;
    141 int* initer;
    142 
    143 inline void init(){
    144     readInteger(n);
    145     readInteger(m);
    146     initer = new int[(const int)(n + 1)];
    147     for(int i = 1; i <= n; i++)
    148         readInteger(initer[i]);
    149     st = SegTree(n, initer);
    150 }
    151 
    152 inline void solve(){
    153     int op, a, b;
    154     while(m--){
    155         readInteger(op);
    156         readInteger(a);
    157         readInteger(b);
    158         if(op == 1){
    159             st.update(st.root, a, b);
    160         }else if(op == 2){
    161             Pair<long long, long long> p = st.query(st.root, a, b);
    162             long long L = b - a + 1;
    163 //            long long inv = pow_mod(L * L % moder, moder - 2);
    164             int inv = getInv(L * L % moder, moder);
    165             long long fm = (L * (p.y % moder) % moder - p.x * p.x % moder + moder) % moder;
    166             long long ans = fm * inv % moder;
    167             printf("%d
    ", (int)ans);
    168         }
    169     }
    170 }
    171 
    172 int main(){
    173     init();
    174     solve();
    175     return 0;
    176 }

      不过这道题只有单点修改,那么,可以考虑用树状数组。树状数组的常数比线段树小这是家喻户晓的事情(两者理论时间复杂度一样)。

      另外鉴于洛谷鬼蓄的评测机,把某些只超一点点的取模符号改成三目运算符,就快了100多ms(吐血)。

      由于我比较懒,又赶去学Splay,所以没有来得急写。


    T2 漂浮的鸭子

      一道强连通分量的裸题。常见的算法是Tarjan:

      1 /**
      2  * luogu.org
      3  * Problem#2049
      4  * Accepted
      5  * Time:150ms
      6  * Memory:18527k
      7  */
      8 #include<iostream>
      9 #include<fstream>
     10 #include<sstream>
     11 #include<cstdio>
     12 #include<cstdlib>
     13 #include<cstring>
     14 #include<ctime>
     15 #include<cctype>
     16 #include<cmath>
     17 #include<algorithm>
     18 #include<stack>
     19 #include<queue>
     20 #include<set>
     21 #include<map>
     22 #include<vector>
     23 using namespace std;
     24 typedef bool boolean;
     25 #define smin(a, b)    (a) = min((a), (b))
     26 #define smax(a, b)    (a) = max((a), (b))
     27 template<typename T>
     28 inline void readInteger(T& u){
     29     char x;
     30     int aFlag = 1;
     31     while(!isdigit((x = getchar())) && x != '-' && x != -1);
     32     if(x == -1)    return;
     33     if(x == '-'){
     34         x = getchar();
     35         aFlag = -1;
     36     }
     37     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
     38     ungetc(x, stdin);
     39     u *= aFlag;
     40 }
     41 
     42 int cv = 0, cc = 0;
     43 stack<int> s;
     44 int* visitID;
     45 int* exitID;
     46 boolean* instack;
     47 boolean* visited;
     48 int* belong;
     49 int* next;
     50 
     51 void getSonMap(int end){
     52     int d;
     53     cc++;
     54     do{
     55         d = s.top();
     56         s.pop();
     57         belong[d] = cc;
     58         instack[d] = false;
     59     }while(d != end);
     60 }
     61 
     62 void Tarjan(int node){
     63     visitID[node] = exitID[node] = ++cv;
     64     visited[node] = true;
     65     s.push(node);
     66     instack[node] = true;
     67     if(!visited[next[node]]){
     68         Tarjan(next[node]);
     69         smin(exitID[node], exitID[next[node]]);
     70     }else if(instack[next[node]]){
     71         smin(exitID[node], visitID[next[node]]);
     72     }
     73     if(exitID[node] == visitID[node])
     74         getSonMap(node);
     75 }
     76 
     77 int n;
     78 int *len;
     79 int *clen;
     80 
     81 inline void init(){
     82     readInteger(n);
     83     visitID = new int[(const int)(n + 1)];
     84     exitID = new int[(const int)(n + 1)];
     85     instack = new boolean[(const int)(n + 1)];
     86     visited = new boolean[(const int)(n + 1)];
     87     belong = new int[(const int)(n + 1)];
     88     next = new int[(const int)(n + 1)];
     89     len = new int[(const int)(n + 1)];
     90     memset(visited, false, sizeof(boolean) * (n + 1));
     91     memset(instack, false, sizeof(boolean) * (n + 1));
     92     for(int i = 1; i <= n; i++){
     93         readInteger(next[i]);
     94         readInteger(len[i]);
     95     }
     96 }
     97 
     98 int result = 0;
     99 boolean* vis;
    100 
    101 inline void solve(){
    102     for(int i = 1; i <= n; i++)
    103         if(!visited[i])
    104             Tarjan(i);
    105     delete[] visitID;
    106     delete[] visited;
    107     delete[] instack;
    108     delete[] exitID;
    109     clen = new int[(const int)(cc + 1)];
    110     vis = new boolean[(const int)(cc + 1)];
    111     memset(vis, false, sizeof(boolean) * (cc + 1)); 
    112     for(int i = 1; i <= n; i++){
    113         if(!vis[belong[i]]){
    114             int j = i;
    115             int l = 0;
    116             while(belong[next[j]] == belong[i] && next[j] != i){
    117                 l += len[j];
    118                 j = next[j];
    119             }
    120             l += len[j];
    121             vis[belong[i]] = true;
    122             smax(result, l);
    123         }
    124     }
    125     printf("%d", result);
    126 }
    127 
    128 int main(){
    129     init();
    130     solve();
    131     return 0;
    132 }

      仔细读题,每个点的出度为1,那么实际上dfs就好了,用不着Tarjan,还开辣么多数组。

     1 /**
     2  * luogu.org
     3  * Problem#2049
     4  * Accepted
     5  * Time:107ms
     6  * Memory:17941k
     7  */
     8 #include<iostream>
     9 #include<fstream>
    10 #include<sstream>
    11 #include<cstdio>
    12 #include<cstdlib>
    13 #include<cstring>
    14 #include<ctime>
    15 #include<cctype>
    16 #include<cmath>
    17 #include<algorithm>
    18 #include<stack>
    19 #include<queue>
    20 #include<set>
    21 #include<map>
    22 #include<vector>
    23 using namespace std;
    24 typedef bool boolean;
    25 #define smin(a, b)    (a) = min((a), (b))
    26 #define smax(a, b)    (a) = max((a), (b))
    27 template<typename T>
    28 inline void readInteger(T& u){
    29     char x;
    30     int aFlag = 1;
    31     while(!isdigit((x = getchar())) && x != '-' && x != -1);
    32     if(x == -1)    return;
    33     if(x == '-'){
    34         x = getchar();
    35         aFlag = -1;
    36     }
    37     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
    38     ungetc(x, stdin);
    39     u *= aFlag;
    40 }
    41 
    42 int n;
    43 int cc = 0;
    44 int *belong;
    45 int *next;
    46 int *len;
    47 int *dist;
    48 int result = 0;
    49 
    50 void dfs(int node, int be){
    51     belong[node] = be;
    52     if(belong[next[node]] == be){
    53         int dis = dist[node] - dist[next[node]] + len[node];
    54         smax(result, dis);
    55     }
    56     if(belong[next[node]] == 0){
    57         dist[next[node]] = dist[node] + len[node];
    58         dfs(next[node], be);
    59     }
    60 }
    61 
    62 inline void init(){
    63     readInteger(n);
    64     belong = new int[(const int)(n + 1)];
    65     next = new int[(const int)(n + 1)];
    66     len = new int[(const int)(n + 1)];
    67     dist = new int[(const int)(n + 1)];
    68     memset(belong, 0, sizeof(int) * (n + 1));
    69     for(int i = 1; i <= n; i++){
    70         readInteger(next[i]);
    71         readInteger(len[i]);
    72     }
    73 }
    74 
    75 
    76 inline void solve(){
    77     for(int i = 1; i <= n; i++)
    78         if(belong[i] == 0){
    79             dist[i] = 0;
    80             dfs(i, ++cc);
    81         }
    82     printf("%d", result);
    83 }
    84 
    85 int main(){
    86     init();
    87     solve();
    88     return 0;
    89 }

    (瞬间剪下33行!)


    T3 最大差值

      找到在i前面最小的一个数,边读边更新最小值,边更新结果。(通常来说不是应该放在第一题吗)

     1 /**
     2  * luogu.org
     3  * Problem#2061
     4  * Accepted
     5  * Time:317ms
     6  * Memory:16406k
     7  */
     8 #include<iostream>
     9 #include<fstream>
    10 #include<sstream>
    11 #include<cstdio>
    12 #include<cstdlib>
    13 #include<cstring>
    14 #include<ctime>
    15 #include<cctype>
    16 #include<cmath>
    17 #include<algorithm>
    18 #include<stack>
    19 #include<queue>
    20 #include<set>
    21 #include<map>
    22 #include<vector>
    23 using namespace std;
    24 typedef bool boolean;
    25 #define smin(a, b)    (a) = min((a), (b))
    26 #define smax(a, b)    (a) = max((a), (b))
    27 template<typename T>
    28 inline void readInteger(T& u){
    29     char x;
    30     int aFlag = 1;
    31     while(!isdigit((x = getchar())) && x != '-' && x != -1);
    32     if(x == -1)    return;
    33     if(x == '-'){
    34         x = getchar();
    35         aFlag = -1;
    36     }
    37     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
    38     ungetc(x, stdin);
    39     u *= aFlag;
    40 }
    41 
    42 int n;
    43 int minv;
    44 int res = 0xffffffff;
    45 
    46 inline void solve(){
    47     readInteger(n);
    48     readInteger(minv);
    49     for(int i = 1, a; i < n; i++){
    50         readInteger(a);
    51         smax(res, a - minv);
    52         smin(minv, a);
    53     }
    54     printf("%d", res);
    55 }
    56 
    57 int main(){
    58     solve();
    59     return 0;
    60 }

    T4 随机数生成器 

      我先讲我会的内容:

     

      变形一下可得:

      最后化简得到:

      由于题目数据范围很大,那么只能过70%的数据,于是便有了分块打表:

     1 /**
     2  * luogu.org
     3  * Problem#2062
     4  */
     5 #include<iostream>
     6 #include<fstream>
     7 #include<sstream>
     8 #include<cstdio>
     9 #include<cstdlib>
    10 #include<cstring>
    11 #include<ctime>
    12 #include<cctype>
    13 #include<cmath>
    14 #include<algorithm>
    15 #include<stack>
    16 #include<queue>
    17 #include<set>
    18 #include<map>
    19 #include<vector>
    20 using namespace std;
    21 typedef bool boolean;
    22 #define smin(a, b)    (a) = min((a), (b))
    23 #define smax(a, b)    (a) = max((a), (b))
    24 template<typename T>
    25 inline void readInteger(T& u){
    26     char x;
    27     int aFlag = 1;
    28     while(!isdigit((x = getchar())) && x != '-' && x != -1);
    29     if(x == -1)    return;
    30     if(x == '-'){
    31         x = getchar();
    32         aFlag = -1;
    33     }
    34     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
    35     ungetc(x, stdin);
    36     u *= aFlag;
    37 }
    38 
    39 double E = 0;
    40 double sum = 0;
    41 
    42 int main(){
    43     freopen("a.txt", "w", stdout);
    44     unsigned int jg = ((1 << 31) - 1) / 400;
    45     cout << "    if(a >= 1 && a < "<< jg <<")    E = 0, sum = 0, q = 2;" << endl;
    46     for(int i = 2; i <= jg * 400; i++){
    47         E = (sum + i) / (i - 1);
    48         sum += E;
    49         if(i % jg == 0){
    50             printf("    else if(a / %d == %d) E = %0.5llf, sum = %0.5llf, q = %d;
    ", jg, i / jg, E, sum, i);
    51         }
    52     }
    53     return 0;    
    54 }

      由于题目的数据范围有问题,所以第9个点TLE了。那么,我还是把官方正解贴出来(这个是我同学推出来告诉我的,鉴于我语文不好,只好贴官方正解了)

     1 /**
     2  * luogu.org
     3  * Problem#2062
     4  * Accepted
     5  * Time:12ms
     6  * Memory:16410k
     7  */
     8 #include<iostream>
     9 #include<fstream>
    10 #include<sstream>
    11 #include<cstdio>
    12 #include<cstdlib>
    13 #include<cstring>
    14 #include<ctime>
    15 #include<cctype>
    16 #include<cmath>
    17 #include<algorithm>
    18 #include<stack>
    19 #include<queue>
    20 #include<set>
    21 #include<map>
    22 #include<vector>
    23 using namespace std;
    24 typedef bool boolean;
    25 #define smin(a, b)    (a) = min((a), (b))
    26 #define smax(a, b)    (a) = max((a), (b))
    27 template<typename T>
    28 inline void readInteger(T& u){
    29     char x;
    30     int aFlag = 1;
    31     while(!isdigit((x = getchar())) && x != '-' && x != -1);
    32     if(x == -1)    return;
    33     if(x == '-'){
    34         x = getchar();
    35         aFlag = -1;
    36     }
    37     for(u = x - '0'; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - '0');
    38     ungetc(x, stdin);
    39     u *= aFlag;
    40 }
    41 
    42 int n;
    43 
    44 inline void init(){
    45     readInteger(n);
    46 }
    47 
    48 double sumer = 0;
    49 double E = 0; 
    50 
    51 inline void solve(){
    52     if(n >= 1000000){
    53         printf("%0.5lf", 1.57721566490123286060651209 + log(n - 1));
    54         return;
    55     }
    56     E = 0;
    57     sumer = 0;
    58     for(int i = 2; i <= n; i++){
    59         E = (sumer + i) / (i - 1);
    60         sumer += E; 
    61     }
    62     printf("%0.5lf", E);
    63 }
    64 
    65 int main(){
    66     init();
    67     solve();
    68     return 0;
    69 }
  • 相关阅读:
    SpringMVC上传文件的三种方式(转载)
    几种流行Webservice框架性能对比(转载)
    @QueryParam和@PathParam使用方法比较
    MyEclipse开发Rest服务入门
    WebService SOAP、Restful和HTTP(post/get)请求区别
    Java WebService入门实例
    WebService 与 Socket 区别
    Double 数据保留两位小数二:直接截取小数后面两位,不进行四舍五入
    SVN 常识
    Android 友盟分享躺过的几个坑,大坑,坑爹啊
  • 原文地址:https://www.cnblogs.com/yyf0309/p/6291204.html
Copyright © 2011-2022 走看看