首页 > 代码库 > [填坑]主席树

[填坑]主席树

     首先,可持久化数据结构,CLJ的论文里有讲。

     通俗点来讲,就是该数据结构保留历史版本信息,对应的有可持久化链表,可持久化线段树,可持久化树状数组。比如对于线段树更新操作,每次更新新建一棵线段树,那么就有任意一次时间点信息。

     当然,这样就非常耗空间,所以,对于线段树,每次只需要对于有更新的节点新建节点,否者可以用前一个版本的顶点(就是连接一下左右孩子就行了),这样,如果每次都是单点更改的话每次也就更改logn个点,空间复杂度nlogn。

     接下来我们讲讲什么是主席树(orz 主席)。

     如果我的理解没错的话(有错轻拍),主席树是一种特殊的线段树,特殊在于它具有前缀性质。也就是说,他对于每个i建立一颗线段树,维护1..i里面数字出现的信息,这样的话他又满足减法性,适合一些特殊问题(比如求区间第K大等经典问题)。

 

Poj2104

    静态查询区间第K大

    直接把出现的数字离散化,离散完建立线段树,接下去,对于每个1..i建立一个线段树,查询了(l, r),那么就是T[r]-T[l-1]的结果(T[i]表示第I棵线段树)

    具体看代码:

    

  1 /*  2  * Author:  Yzcstc  3  * Created Time:  2014/7/8 13:24:35  4  * File Name: poj2104.cpp  5  */  6 #include<cstdio>  7 #include<iostream>  8 #include<cstring>  9 #include<cstdlib> 10 #include<cmath> 11 #include<algorithm> 12 #include<string> 13 #include<map> 14 #include<set> 15 #include<vector> 16 #include<queue> 17 #include<stack> 18 #include<ctime> 19 #define rep(i, a, b) for (int i = (a); i <= (b); ++i) 20 #define red(i, a, b) for (int i = (a); i >= (b); --i) 21 #define M0(x)  memset(x, 0, sizeof(x)) 22 #define MP make_pair 23 #define PB push_back 24 #define eps 1e-8 25 #define pi acos(-1.0) 26 #define N 101000 27 #define M (35 * N) 28 typedef long long LL; 29 using namespace std; 30 int lson[M], rson[M], c[M]; 31 int a[N], n, m, q, tot, T[N]; 32 vector<int> v;  33  34 void init(){ 35     tot = 0; 36     v.clear(); 37     for (int i = 1; i <= n; ++i) 38         scanf("%d", &a[i]), v.push_back(a[i]); 39     sort(v.begin(), v.end()); 40     v.erase(unique(v.begin(), v.end()), v.end()); 41     m = v.size(); 42 } 43  44 int hash(const int x){ 45     return lower_bound(v.begin(), v.end(), x) - v.begin() + 1; 46 } 47  48 int build(int l, int r){ 49     int root = tot++; 50     c[root] = 0; 51     if (l < r){ 52         int mid = (l + r) >> 1; 53         build(l , mid); 54         build(mid + 1, r); 55     } 56     return root; 57 } 58  59 int updata(int root, int p, int val){ //  60     int newroot = tot++, tmp = newroot; 61     int l = 1, r = m; 62     while (1){ 63          c[newroot] = c[root] + val; 64          if (l == r) break; 65          int mid = (l + r) >> 1; 66          if (p <= mid){ 67              lson[newroot] = tot++; rson[newroot] = rson[root]; //位于左子树,左子树更新节点,右子树用原来节点  68              newroot = lson[newroot]; root = lson[root]; 69              r = mid; 70          } 71          else  72          { 73             lson[newroot] = lson[root]; rson[newroot] = tot++; //位于右子树  74             newroot = rson[newroot]; root = rson[root]; 75             l = mid + 1; 76          } 77     } 78     return tmp; 79 } 80  81 int query(int lroot, int rroot, int k){   82     int ret = 0, l = 1, r = m; 83     while (1){ 84         if (l == r) return v[l - 1]; 85         int mid = (l + r) >> 1; 86         if (c[lson[rroot]] - c[lson[lroot]] >= k){ //左子树已经至少包含K个  87              rroot = lson[rroot]; 88              lroot = lson[lroot]; 89              r = mid; 90         } 91         else  92         { 93             k -= (c[lson[rroot]] - c[lson[lroot]]); //答案维护右子树  94             rroot = rson[rroot]; 95             lroot = rson[lroot]; 96             l = mid + 1; 97         } 98     } 99     return l;100 }101 102 void solve(){103     T[0] = build(1, m);104     for (int i = 1; i <= n; ++i){105         int p = hash(a[i]);106         T[i] = updata(T[i-1], p, 1);107     }108     int l, r, k;109     for (int i = 0; i < q; ++i){110          scanf("%d%d%d", &l, &r, &k);111          printf("%d\n", query(T[l-1], T[r], k));112     }113     114 }115 116 int main(){117     freopen("a.in", "r", stdin);118     freopen("a.out", "w", stdout);119     while (scanf("%d%d", &n, &q) != EOF){120         init();121         solve();122     }123     fclose(stdin);  fclose(stdout);124     return 0;125 }
View Code

hdu4417

    更上面差不多的题目,只不过查询改成了给定l,r,h,查询l,r间多少个不大于h。

    找到原数组中第一个<=h的数的下标P,直接查询P前面有多少个即可。

  1 /*  2  * Author:  Yzcstc  3  * Created Time:  2014/7/8 15:45:55  4  * File Name: hdu4417.cpp  5  */  6 #include<cstdio>  7 #include<iostream>  8 #include<cstring>  9 #include<cstdlib> 10 #include<cmath> 11 #include<algorithm> 12 #include<string> 13 #include<map> 14 #include<set> 15 #include<vector> 16 #include<queue> 17 #include<stack> 18 #include<ctime> 19 #define rep(i, a, b) for (int i = (a); i <= (b); ++i) 20 #define red(i, a, b) for (int i = (a); i >= (b); --i) 21 #define M0(x)  memset(x, 0, sizeof(x)) 22 #define MP make_pair 23 #define PB push_back 24 #define eps 1e-8 25 #define pi acos(-1.0) 26 #define N 101000 27 #define M (N * 35) 28 typedef long long LL; 29 using namespace std; 30 int a[N], t[N], n, m, q, cas; 31 int c[M], lson[M], rson[M], tot, T[N]; 32  33 int build(const int l,const int r){ 34      int root = tot++; 35      c[root] = 0; 36      if (l < r){ 37         int mid = (l + r) >> 1; 38         build(l, mid); 39         build(mid + 1, r);       40      } 41      return root; 42 } 43  44 void init(){ 45     tot = 0; 46     scanf("%d%d", &n, &q); 47     for (int i = 1; i <= n; ++i) 48         scanf("%d", &a[i]), t[i] = a[i]; 49     sort(t + 1, t + 1 + n); 50     m = unique(t + 1, t + 1 + n) - t - 1; 51 } 52  53 int hash(const int x){ 54     return lower_bound(t + 1, t + m + 1, x) - t; 55 } 56  57 int updata(int root,const int p,const int val){ 58     int newroot = tot++, tmp = newroot; 59     int l = 1, r = m; 60     while (1){ 61         c[newroot] = c[root] + val; 62         if (l == r) break; 63         int mid = (l + r) >> 1; 64         if (p <= mid){ 65             lson[newroot] = tot++; rson[newroot] = rson[root]; 66             newroot = lson[newroot]; root = lson[root]; 67             r = mid; 68         } 69         else 70         { 71             lson[newroot] = lson[root]; rson[newroot] = tot++; 72             newroot = rson[newroot]; root = rson[root]; 73             l = mid + 1; 74         } 75     } 76     return tmp; 77 } 78  79 int query(int lroot, int rroot,const int p){ 80     if (!p) return 0; 81     int ret = 0, l = 1, r = m; 82     while (1){ 83           if (l == r) break; 84           int mid = (l + r) >> 1; 85           if (p <= mid){ 86                 lroot = lson[lroot]; 87                 rroot = lson[rroot]; 88                 r = mid;    89           }     90           else  91           { 92                 ret += (c[lson[rroot]] - c[lson[lroot]]); 93                 lroot = rson[lroot]; 94                 rroot = rson[rroot]; 95                 l = mid + 1;         96           } 97     } 98     return ret + c[rroot] - c[lroot]; 99 }100 101 void solve(){102     T[0] = build(1, m);103     for (int i = 1; i <= n; ++i){104          int p = hash(a[i]);105          T[i] = updata(T[i-1], p, 1); 106     }107     for (int i = 0; i < q; ++i){108         int l, r, h;109         scanf("%d%d%d", &l, &r, &h);110         l++, r++;111         int p = hash(h);112         while (p > 0 && t[p] > h) --p;113         printf("%d\n", query(T[l-1], T[r], p));    114     }115 }116 117 int main(){118  //   freopen("a.in", "r", stdin);119   //  freopen("a.out", "w", stdout);120     scanf("%d", &cas);121     for (int i = 1; i <= cas; ++i){122         printf("Case %d:\n", i);123         init();124         solve();125     }126     fclose(stdin);  fclose(stdout);127     return 0;128 }
View Code

 

hdu4348

    更定n个数,然后4个操作:

         1. C l r d: [l, r]区间都增加d,并且时间点+1
         2. Q l r:查询当前[l,r]的和

         3. H l r t: 查询t时间点时[l,r]的和
         4. B t:数组返回到t时间的状态

    可以用离线算法或者在线算法。、,主要说说在线算法吧。。

     1)可以用采用可持久化树状数组,具体的话采用这位大牛博客的方法(区间修改,区间和的查询),然后对于每个时间点维护弄一个树状数组,

          遇到Back操作就把T以上的时间点出栈。。

     2)采用可持久化线段树,但是区间更改直接更改到某一小段(对于[l,r],由顶至下的所有第一个满足[L,r] <=[l,r]才需要更改),往下就不用更改,查询时把父节点增加值加上就行

    code(Bit):

  1 /*  2  * Author:  Yzcstc  3  * Created Time:  2014/7/9 12:59:07  4  * File Name: hdu4348_bit.cpp  5  */  6 #include<cstdio>  7 #include<iostream>  8 #include<cstring>  9 #include<cstdlib> 10 #include<cmath> 11 #include<algorithm> 12 #include<string> 13 #include<map> 14 #include<set> 15 #include<vector> 16 #include<queue> 17 #include<stack> 18 #include<ctime> 19 #define rep(i, a, b) for (int i = (a); i <= (b); ++i) 20 #define red(i, a, b) for (int i = (a); i >= (b); --i) 21 #define M0(x)  memset(x, 0, sizeof(x)) 22 #define MP make_pair 23 #define PB push_back 24 #define eps 1e-8 25 #define pi acos(-1.0) 26 #define N 101000 27 typedef long long LL; 28 using namespace std; 29 struct oo{ 30     LL d, dt; 31     int T; 32     oo(LL _d = 0, LL _dt = 0, int _T = 0):d(_d),dt(_dt), T(_T){} 33     void updata(long long d1, long long dt1, int T1){ 34         d += d1; 35         dt += dt1; 36         T = T1; 37     } 38 }; 39 vector<oo> b[N]; //b[x]记录b[x][i]记录第b[i].T个时间点的记录  40 long long a[N], sum[N]; 41 int n, m; 42  43 int lowbit(const int x){ 44     return x & (-x); 45 } 46  47 void updata(int x,const long long v,const int T){ 48     long long vt = v * x; 49     for (; x <= n; x += lowbit(x)){ 50         int sz = b[x].size(); 51         b[x].PB(b[x][sz-1]); //需要更改的点新建,否则信息都跟b[x][sz-1]一样(T不一样,但是不影响)  52         sz++; 53         b[x][sz-1].updata(v, vt, T); 54     } 55 } 56  57 long long query(int x,const int T){ 58     long long sd = 0, sdt = 0; 59     int cur_x = x; 60     for (; x; x -= lowbit(x)){ 61         int sz = b[x].size(); 62         while (sz && b[x][sz-1].T > T) --sz; //你会疑惑可能b[x][sz-1]最后的时间点不是T(因为前面新增时没更改到)  63         sd += b[x][sz-1].d; //那么就对了,没更改到前一个节点信息跟现在的一模一样,直接用不就得了何必更改。。  64         sdt += b[x][sz-1].dt; 65     } 66     return (cur_x + 1) * sd - sdt; // 67 } 68  69 long long query(const int l,const int r,const int T){ 70     return sum[r] - sum[l-1] + query(r, T) - query(l-1, T); 71 } 72  73 void goback(int T){ 74     for (int i = 1; i <= n; ++i){ 75         int sz = b[i].size(); 76         while (sz && b[i][sz-1].T > T) b[i].pop_back(), sz--; 77     } 78 } 79  80 void init(){ 81     for (int i = 1; i <= n; ++i){ 82         b[i].clear(); 83         b[i].PB(oo(0LL, 0LL, 0)); 84     } 85     for (int i = 1; i <= n; ++i) 86         scanf("%I64d", &a[i]), sum[i] = sum[i-1] + a[i]; 87 } 88  89 void solve(){ 90     char S[12]; 91     int l, r, d; 92     int now = 0; 93     for (int i = 0; i < m; ++i){ 94         scanf("%s", S); 95         if (S[0] == Q){ 96             scanf("%d%d", &l, &r); 97             printf("%I64d\n", query(l, r, now)); 98         } 99         if (S[0] == C){100             scanf("%d%d%d", &l, &r, &d);101             ++now;102             updata(l, d, now);103             updata(r+1, -d, now);104         }105         if (S[0] == H){106             scanf("%d%d%d", &l, &r, &d);107             printf("%I64d\n", query(l, r, d));108         }109         if (S[0] == B){110             scanf("%d", &l);111             now = l;112             goback(l);113         }114     }115 }116 117 int main(){118     freopen("a.in", "r", stdin);119     freopen("a.out", "w", stdout);120     int cas = 0;121     while (scanf("%d%d", &n, &m) != EOF){122         if (cas++) puts("");123         init();124         solve();125     }126     fclose(stdin);  fclose(stdout);127     return 0;128 }
View Code

   code(线段树版本,好像时间还少点):

  1 /*  2  * Author:  Yzcstc  3  * Created Time:  2014/7/9 12:59:07  4  * File Name: hdu4348_bit.cpp  5  */  6 #include<cstdio>  7 #include<iostream>  8 #include<cstring>  9 #include<cstdlib> 10 #include<cmath> 11 #include<algorithm> 12 #include<string> 13 #include<map> 14 #include<set> 15 #include<vector> 16 #include<queue> 17 #include<stack> 18 #include<ctime> 19 #define rep(i, a, b) for (int i = (a); i <= (b); ++i) 20 #define red(i, a, b) for (int i = (a); i >= (b); --i) 21 #define M0(x)  memset(x, 0, sizeof(x)) 22 #define MP make_pair 23 #define PB push_back 24 #define eps 1e-8 25 #define pi acos(-1.0) 26 #define N 110010 27 #define M 3450100 28 typedef long long LL; 29 using namespace std; 30 int lson[M], rson[M], c[M], tot, a[N], T[N], now, n, m; 31 long long sum[M]; 32  33 int build(int l, int r){ 34     int root = tot++; 35     c[root] = 0; 36     if (l == r) sum[root] = a[l]; 37     else  38     { 39          int mid = (l + r) >> 1; 40          lson[root] = build(l, mid); 41          rson[root] = build(mid + 1, r); 42          sum[root] = sum[lson[root]] + sum[rson[root]]; 43     } 44     return root; 45 } 46  47 int updata(int rt, const int L, const int R, const int l,const int r, const int v){ 48     int root = tot++; 49     c[root] = c[rt]; sum[root] = sum[rt]; 50     lson[root] =  lson[rt]; rson[root] = rson[rt]; 51     if (l <= L && R <= r){ 52            c[root] += v; 53            sum[root] += (__int64)(R-L+1) * v;       54            return root; 55     } 56     int mid = (L + R) >> 1; 57     if (l <= mid)  58           lson[root] = updata(lson[rt], L, mid, l, r, v); 59     if (r > mid)  60           rson[root] = updata(rson[rt], mid+1, R, l, r, v);  61     sum[root] = sum[lson[root]] + sum[rson[root]] + c[root] * (R-L+1);   62     return root; 63 } 64  65 long long query(int rt,const int L, const int R, const int l, const int r, int v){ 66      if (l <= L && R <= r) 67            return sum[rt] + v * (R-L+1); 68      int mid = (L + R) >> 1; 69      long long ret = 0; 70      if (l <= mid)  71          ret += query(lson[rt], L, mid, l, r, v + c[rt]); 72      if (r > mid) 73          ret += query(rson[rt], mid+1, R, l, r, v + c[rt]); 74      return ret; 75 } 76  77 void goback(int time){ 78      if (now == time) return; 79      now = time; 80      tot = T[time+1];  81 } 82  83 void init(){ 84     for (int i = 1; i <= n; ++i) 85         scanf("%d", &a[i]); 86     tot = 0; 87     T[0] = build(1, n); 88 } 89  90 void solve(){ 91     char S[12]; 92     int l, r, d; 93     now = 0; 94     for (int i = 1; i <= m; ++i){ 95         scanf("%s", S); 96         if (S[0] == Q){ 97             scanf("%d%d", &l, &r); 98             printf("%I64d\n", query(T[now], 1, n, l, r, 0)); 99         }100         if (S[0] == C){101             scanf("%d%d%d", &l, &r, &d);102             ++now;103             T[now] = updata(T[now-1], 1, n, l, r, d);104         }105         if (S[0] == H){106             scanf("%d%d%d", &l, &r, &d);107             printf("%I64d\n", query(T[d], 1, n, l, r, 0));108         }109         if (S[0] == B){110             scanf("%d", &l);111             goback(l);112         }113     }114 }115 116 int main(){117 //    freopen("a.in", "r", stdin);118 //    freopen("a.out", "w", stdout);119     int cas = 0;120     while (scanf("%d%d", &n, &m) != EOF){121         if (cas++) puts("");122         init();123         solve();124     }125     fclose(stdin);  fclose(stdout);126     return 0;127 }
View Code

 

Zoj2112&&Bzoj1901

    动态区间第K大

    首先,如果是静态的话,那么可以直接用主席树维护。但是更改问题就来了。

    不过试想一下,如果知道某个节点前面的修改情况,那么问题不就解决了吗。这个不就可以用树状数组来维护吗。。

     举个栗子把:

     比如原数组是: 1 5 2 3 4 6

     当前修改信息是:1(位置1) -> 2, 3(位置4) ->4

     那么在查询[2,4]第2大时,比如对于4,我们查询在原数组区间中为第2大,前面更改信息是少了3,多了4,一加一减为0,答案就是4了。

     具体实现的话:就是对于N个线段树扔进树状数组里进行维护,也就是说树状数组的每个节点对应一棵线段树。

     代码太丑就不贴了。。

     当然也可以用线段树套平衡树的做法实现。。不过太麻烦不写了。。

     具体点这

 

Spoj10628&&Bzoj2588

    树上第K大:(spoj)给定u,v,k,求u到v路径上的第K大

                    (bzoj)给定u,v,k,求u ^ lastans到v路径上的第K大,lastans为上次询问答案

    对于spoj10628,可以离线求出lca,但是bzoj只能在线。我用的是欧拉序列+st求的。。

    其他的话,就判断root->u,root->v,root->lca之间做即可。传统的主席树是在线性上的。。这里改成树的即可

    具体看代码吧

   code:

  1 /*  2  * Author:  Yzcstc  3  * Created Time:  2014/7/10 16:04:29  4  * File Name: spoj10628.cpp  5  */  6 #include<cstdio>  7 #include<iostream>  8 #include<cstring>  9 #include<cstdlib> 10 #include<cmath> 11 #include<algorithm> 12 #include<string> 13 #include<map> 14 #include<set> 15 #include<vector> 16 #include<queue> 17 #include<stack> 18 #include<ctime> 19 #define rep(i, a, b) for (int i = (a); i <= (b); ++i) 20 #define red(i, a, b) for (int i = (a); i >= (b); --i) 21 #define M0(x)  memset(x, 0, sizeof(x)) 22 #define MP make_pair 23 #define PB push_back 24 #define eps 1e-8 25 #define pi acos(-1.0) 26 #define two(i) (1 << i) 27 #define N 101000 28 #define M 4100000 29 typedef long long LL; 30 using namespace std; 31 int T[N << 1], t[N << 1], a[N << 1], n, m, q; 32 int lson[M], rson[M], c[M], tot; 33 int f[N<<1][20], dep[N<<1], fv[N<<1], lv[N<<1], fa[N<<1], d[N << 1], inx; 34 vector<int> e[N << 1]; 35  36 void dfs(int u, int depth){ 37     dep[u] = depth; 38     fv[u] = lv[u] = ++inx; 39     d[inx] = u; 40     for (int i = 0; i < e[u].size(); ++i){ 41         int v = e[u][i]; 42         if (dep[v]) continue; 43         fa[v] = u; 44         dfs(v, depth + 1); 45         d[lv[u] = ++inx] = u; 46     } 47          48 } 49  50 void initrmq(){ //求出st的dp数组  51     M0(fa); 52     M0(dep); 53     dfs(1, 1); 54     M0(f); 55     for (int i = 1; i <= inx; ++i) 56         f[i][0] = d[i]; 57     for (int j = 1; two(j) <= inx; ++j) 58         for (int i = 1; i + two(j) - 1 <= inx; ++i) 59            f[i][j] = (dep[f[i][j-1]] < dep[f[i + two(j-1)][j-1]]) ? f[i][j-1] : f[i+two(j-1)][j-1];           60 } 61  62 void init(){ 63     tot = inx = 0; 64     M0(a); 65     for (int i = 0; i <= n; ++i) e[i].clear(); 66     for (int i = 1; i <= n; ++i) 67         scanf("%d", &a[i]), t[i-1] = a[i]; 68     for (int i = 1; i < n; ++i){ 69         int u, v; 70         scanf("%d%d", &u, &v); 71         e[u].PB(v); 72         e[v].PB(u); 73     } 74     sort(t, t + n); 75     m = unique(t, t + n) - t; 76     initrmq(); 77 } 78  79 int queryrmq(const int L,const int R){ //st查询最小值  80     int l = min(fv[L], fv[R]); 81     int r = max(lv[L], lv[R]); 82     int k = (int)(log(r-l+1.0) / log(2.0)); 83     return dep[f[l][k]] < dep[f[r-two(k)+1][k]] ? f[l][k] : f[r-two(k)+1][k]; 84 } 85  86 int hash(const int x){ 87     return lower_bound(t, t + m, x) - t; 88 } 89  90 int build(const int l,const int r){ 91     int root = tot++; 92     if (l < r){ 93         int mid = (l + r) >> 1; 94         lson[root] = build(l, mid); 95         rson[root] = build(mid+1, r); 96     } 97     return root; 98 } 99 100 int updata(int rt, const int p, const int v){101     int root = tot++, tmp = root;102     int l = 0, r = m - 1;103     while (1){104         c[root] = c[rt] + v;105         if (l == r) break;106         int mid = (l + r) >> 1;107         if (p <= mid){108             lson[root] = tot++; rson[root] = rson[rt];109             root = lson[root]; rt = lson[rt];110             r = mid;111         }112         else113         {114             lson[root] = lson[rt]; rson[root] = tot++;115             root = rson[root]; rt = rson[rt];116             l = mid + 1;117         }118     }119     return tmp;120 }121 122 int query(int rtu, int rtv, int rtf, int fp, int k){123     int l = 0, r = m - 1;124     while (l < r){125         int mid = (l + r) >> 1;126         int tmp = c[lson[rtu]] + c[lson[rtv]] - 2 * c[lson[rtf]] + (fp <= mid && fp >= l); //多减了lca的答案,所以要加上去 127         if (tmp >= k){128             rtu = lson[rtu];129             rtv = lson[rtv];130             rtf = lson[rtf];131             r = mid;132         }133         else134         {135             rtu = rson[rtu];136             rtv = rson[rtv];137             rtf = rson[rtf];138             k -= tmp;139             l = mid + 1;    140         }141     }142     return l;143 }144 145 void dfs(const int u){ //树结构上建主席树 146     T[u] = updata(T[fa[u]], hash(a[u]), 1);147     for (int i = 0; i < e[u].size(); ++i){148         int v = e[u][i];149         if (v == fa[u]) continue;150         dfs(v);151     }152 }153 154 void solve(){155     int u, v, k, fuv;156     T[0] = build(0, m-1);157     dfs(1);158     for (int i = 0; i < q; ++i){159         scanf("%d%d%d", &u, &v, &k);160         fuv = queryrmq(u, v);161         printf("%d\n", t[query(T[u], T[v], T[fuv],hash(a[fuv]), k)]);162     }163 }164 165 int main(){166 //    freopen("a.in", "r", stdin);167 //    freopen("a.out", "w", stdout);168     while (scanf("%d%d", &n, &q) != EOF){169         init();170         solve();171     }172     fclose(stdin);  fclose(stdout);173     return 0;174 }
View Code