打了快一星期的qtree终于打完了- - (其实还有两题改不出来弃疗了QAQ)
orz神AK一星期前就虐完QTREE
避免忘记还是简单写下题解吧0 0
题意:
给出一颗带边权树
一个操作:修改边权
还有一个询问:求x到y路径上边权最大值
树链剖分模版题- -blabla
代码:
1 #include <cstdio> 2 #include <cstring> 3 const int N=10001; 4 struct inli{ 5 int next,data,lon; 6 inli(const int a=0,const int b=0,const int c=0): 7 next(a),data(b),lon(c){} 8 }line[N*2]; 9 struct info{ 10 int x,y; 11 info(const int a=0,const int b=0): 12 x(a),y(b){} 13 }sline[N]; 14 int n,t,nl,dfss,back[N],tree[N*4],deep[N],num[N],hard[N],dfn[N],fl[N],fat[N],gr[N],son[N]; 15 int st,si; 16 char s[10]; 17 int max(int x,int y){ return x>y ? x : y; } 18 void swap(int &x,int &y){ int t=x; x=y,y=t; } 19 void clean(){ 20 nl=dfss=0; 21 memset(son,0,sizeof(son)); 22 memset(hard,0,sizeof(hard)); 23 memset(tree,0,sizeof(tree)); 24 } 25 void makehard(int t){ 26 num[t]=1; 27 for (int i=son[t];i;i=line[i].next) 28 if (line[i].data!=fat[t]){ 29 int ne=line[i].data; 30 fat[ne]=t; 31 deep[ne]=deep[t]+1; 32 fl[ne]=line[i].lon; 33 makehard(ne); 34 num[t]+=num[ne]; 35 if (num[hard[t]]<num[ne]) hard[t]=ne; 36 } 37 } 38 void dfs(int t,int gra){ 39 dfn[t]=++dfss; 40 back[dfss]=t; 41 gr[t]=gra; 42 if (hard[t]) dfs(hard[t],gra); 43 for (int i=son[t];i;i=line[i].next){ 44 int ne=line[i].data; 45 if (ne!=fat[t] && ne!=hard[t]) dfs(ne,ne); 46 } 47 } 48 void build(int l,int r,int rt){ 49 if (l==r-1){ 50 tree[rt]=fl[back[r]]; 51 return; 52 } 53 int mid=(l+r)/2; 54 build(l,mid,rt*2); 55 build(mid,r,rt*2+1); 56 tree[rt]=max(tree[rt*2],tree[rt*2+1]); 57 } 58 int getmax(int l,int r,int rt,int x,int y){ 59 if (x==y) return 0; 60 if (x<=l && r<=y) return tree[rt]; 61 int mid=(l+r)/2,res=0; 62 if (x<mid) res=max(res,getmax(l,mid,rt*2,x,y)); 63 if (mid<y) res=max(res,getmax(mid,r,rt*2+1,x,y)); 64 return res; 65 } 66 int getans(int x,int y){ 67 if (x==y) return 0; 68 if (gr[x]==gr[y]){ 69 if (deep[x]>deep[y]) swap(x,y); 70 return getmax(1,n,1,dfn[x],dfn[y]); 71 } 72 if (deep[gr[x]]<deep[gr[y]]) swap(x,y); 73 return max(getans(fat[gr[x]],y),max(getmax(1,n,1,dfn[gr[x]],dfn[x]),fl[gr[x]])); 74 } 75 void change2(int l,int r,int rt,int x,int y){ 76 if (l+1==r) return (void)(tree[rt]=y); 77 int mid=(l+r)/2; 78 if (x<mid) change2(l,mid,rt*2,x,y); 79 else change2(mid,r,rt*2+1,x,y); 80 tree[rt]=max(tree[rt*2],tree[rt*2+1]); 81 } 82 void change(int t,int s){ 83 int x=sline[t].x,y=sline[t].y; 84 if (deep[x]>deep[y]) swap(x,y); 85 if (gr[x]==gr[y]) change2(1,n,1,dfn[x],s); 86 else fl[y]=s; 87 } 88 int main(){ 89 freopen("spoj375.in","r",stdin); 90 freopen("spoj375.out","w",stdout); 91 for (scanf("%d",&t);t;t--){ 92 clean(); 93 scanf("%d\n",&n); 94 int x,y,z; 95 for (int i=1;i<n;i++){ 96 scanf("%d%d%d\n",&x,&y,&z); 97 line[++nl]=inli(son[x],y,z),son[x]=nl; 98 line[++nl]=inli(son[y],x,z),son[y]=nl; 99 sline[i]=info(x,y); 100 } 101 makehard(1); 102 dfs(1,1); 103 build(1,n,1); 104 int i=0; 105 while (1){ 106 si=++i; 107 st=t; 108 if (i==9995) 109 i=9995; 110 if (t==2) 111 t=2; 112 if (t==9 && i==9999) 113 t=9; 114 scanf("%s",s); 115 if (s[0]=='Q'){ 116 scanf("%d%d\n",&x,&y); 117 printf("%d\n",getans(x,y)); 118 } 119 if (s[0]=='C'){ 120 scanf("%d%d\n",&x,&y); 121 change(x,y); 122 } 123 if (s[0]=='D') break; 124 if (n==2) 125 n=2; 126 } 127 } 128 fclose(stdin); 129 fclose(stdout); 130 }
题意:
给出一颗带边权树 两个询问
1.求x到y路径上边权和
2.求x到y路径上的第k条边的边权
边权和还是树链剖分模版- -
求第k条边 刚想了一下貌似树剖也能做 但是我是用倍增的
代码:
1 #include <cstdio> 2 #include <cstring> 3 const int N=10001; 4 struct inli{ 5 int next,data,lon; 6 inli(const int a=0,const int b=0,const int c=0): 7 next(a),data(b),lon(c){} 8 }line[N*2]; 9 int t,n,nl,deep[N],son[N],fat[N][20],dis[N][20]; 10 char s[10]; 11 void swap(int &x,int &y){ int t=x; x=y,y=t; } 12 void clean(){ 13 nl=0; 14 for (int i=1;i<=n;i++){ 15 son[i]=0; 16 memset(fat[i],0,sizeof(fat[i])); 17 } 18 } 19 void makefat(int t){ 20 for (int i=1;fat[fat[t][i-1]][i-1];++i){ 21 fat[t][i]=fat[fat[t][i-1]][i-1]; 22 dis[t][i]=dis[t][i-1]+dis[fat[t][i-1]][i-1]; 23 } 24 for (int i=son[t];i;i=line[i].next) 25 if (line[i].data!=fat[t][0]){ 26 int ne=line[i].data; 27 deep[ne]=deep[t]+1; 28 fat[ne][0]=t; 29 dis[ne][0]=line[i].lon; 30 makefat(ne); 31 } 32 } 33 int getdis(int x,int y){ 34 if (x==y) return 0; 35 if (deep[x]!=deep[y]){ 36 if (deep[x]<deep[y]) swap(x,y); 37 int i=0; 38 for (;deep[fat[x][i]]>=deep[y] && fat[x][i];++i); 39 --i; 40 return dis[x][i]+getdis(fat[x][i],y); 41 } 42 if (fat[x][0]==fat[y][0]) return dis[x][0]+dis[y][0]; 43 int i=0; 44 for (;fat[x][i]!=fat[y][i] && fat[x][i];++i); 45 --i; 46 return dis[x][i]+dis[y][i]+getdis(fat[x][i],fat[y][i]); 47 } 48 int getgr(int x,int y){ 49 if (x==y) return x; 50 if (deep[x]!=deep[y]){ 51 if (deep[x]<deep[y]) swap(x,y); 52 int i=0; 53 for (;deep[fat[x][i]]>=deep[y] && fat[x][i];++i); 54 --i; 55 return getgr(fat[x][i],y); 56 } 57 if (fat[x][0]==fat[y][0]) return fat[x][0]; 58 int i=0; 59 for (;fat[x][i]!=fat[y][i] && fat[x][i];++i); 60 --i; 61 return getgr(fat[x][i],fat[y][i]); 62 } 63 int getans(int t,int s){ 64 if (s==1) return t; 65 int i=0; 66 for (;deep[t]-deep[fat[t][i]]+1<=s && fat[t][i];++i); 67 --i; 68 return getans(fat[t][i],s-(deep[t]-deep[fat[t][i]])); 69 } 70 int main(){ 71 freopen("spoj913.in","r",stdin); 72 freopen("spoj913.out","w",stdout); 73 for (scanf("%d",&t);t;t--){ 74 scanf("%d\n",&n); 75 clean(); 76 int x,y,z; 77 for (int i=1;i<n;i++){ 78 scanf("%d%d%d\n",&x,&y,&z); 79 line[++nl]=inli(son[x],y,z),son[x]=nl; 80 line[++nl]=inli(son[y],x,z),son[y]=nl; 81 } 82 makefat(1); 83 while (1){ 84 scanf("%s",s); 85 if (s[1]=='I'){ 86 scanf("%d%d\n",&x,&y); 87 printf("%d\n",getdis(x,y)); 88 } 89 if (s[0]=='K'){ 90 scanf("%d%d%d\n",&x,&y,&z); 91 int gr=getgr(x,y); 92 if (deep[x]-deep[gr]+1<z){ 93 swap(x,y); 94 z=deep[x]+deep[y]-deep[gr]*2+2-z; 95 } 96 printf("%d\n",getans(x,z)); 97 } 98 if (s[1]=='O') break; 99 } 100 puts(""); 101 } 102 fclose(stdin); 103 fclose(stdout); 104 }
题意:
给出一颗点初始全白的树
一个操作:修改点的颜色
一个询问:求1到点x的最近黑点 没有则输出-1
这题我觉得能用动态树做
询问的时候把x access到根 splay上维护深度最小的黑点
树链剖分也可以做 线段树维护最前面的黑点即可(貌似比较简单- -)
这题我貌似就yy了一下没打- -
题意:
给出一颗点初始全白的带边权树
一个操作:修改点的颜色
一个询问:求最远的两个白色点的距离
QAQ这题被spoj卡时了啊 根本调不出来- -
其实这题好像是去湖南培训的一道题的弱化版- - 我竟然没想出来orz
我的做法是点分治+3*堆
我们定义某重心的子树的重心是 该重心的重儿子 反之重父亲
维护第一个堆que1维护 该点管辖范围内的点到该点重父亲的距离最大值
第二个堆que2维护 该点的每个重儿子的que1的堆顶的最大值(如果该点为白点 要插入一个dis为0的值)
每个que2的前2大的距离和即为两白点经过该点答案
第三个堆ans3就维护所有的que2的前2大的距离和的最大值
因为我用的是priority_queue 所以不支持删除- - 于是我就每个对打了一个时间戳
一修改3个堆一个套一个全部要改 整个世界格局混乱orz 思路不清晰就很容易晕
这题我打了3天啊QAQ(最后还没调出来←_←)
这题没A就不贴代码了- -
题意:
给出一颗点初始全白的带边权树
一个操作:修改点的颜色
一个询问:求离点x最远的白点的距离
这题和上题做法差不多 枚举管辖范围包括x的重心即可
因为上一题被卡时了 - - 这题也不敢打orz
题意:
给出一颗点初始全白的树
一个操作:修改点的颜色
一个询问:求点x与多少点相连 两点相连条是这两点的路径上的点都与点x的颜色相同
这题我是用树链剖分做的
维护f[2][i]表示i点为黑色或白色时 i的子树中与i相连的点的个数
那么x点的答案就是x点的最浅相连祖先的f[col[x]]值
当修改某点的颜色时 就修改该点到最浅相连祖先的父亲的f值即可
这题也可以用动态树做
详见QTREE7- - 233为什么和神ak写的一样
代码:
1 #include <cstdio> 2 const int N=100001; 3 struct inli{ 4 int next,data; 5 inli(const int a=0,const int b=0): 6 next(a),data(b){} 7 }line[N*2]; 8 int n,m,nl,dfss,deep[N],gr[N],hard[N],num[N],back[N],dfn[N],son[N],tree[2][N*4],fat[N][20],coltree[N*4],col[N]; 9 void makehard(int t){ 10 for (int i=1;fat[fat[t][i-1]][i-1];++i) fat[t][i]=fat[fat[t][i-1]][i-1]; 11 num[t]=1; 12 for (int i=son[t];i;i=line[i].next) 13 if (line[i].data!=fat[t][0]){ 14 int ne=line[i].data; 15 fat[ne][0]=t; 16 deep[ne]=deep[t]+1; 17 makehard(ne); 18 num[t]+=num[ne]; 19 if (num[ne]>num[hard[t]]) hard[t]=ne; 20 } 21 } 22 void dfs(int t,int gra){ 23 gr[t]=gra; 24 dfn[t]=++dfss; 25 back[dfss]=t; 26 if (hard[t]) dfs(hard[t],gra); 27 for (int i=son[t];i;i=line[i].next){ 28 int ne=line[i].data; 29 if (ne!=fat[t][0] && ne!=hard[t]) dfs(ne,ne); 30 } 31 } 32 33 void pushdown(int t){ 34 tree[0][t*2]+=tree[0][t]; 35 tree[0][t*2+1]+=tree[0][t]; 36 tree[0][t]=0; 37 tree[1][t*2]+=tree[1][t]; 38 tree[1][t*2+1]+=tree[1][t]; 39 tree[1][t]=0; 40 } 41 void build(int l,int r,int rt){ 42 if (l==r){ 43 tree[0][rt]=num[back[l]]; 44 tree[1][rt]=1; 45 return; 46 } 47 int mid=(l+r)/2; 48 build(l,mid,rt*2); 49 build(mid+1,r,rt*2+1); 50 } 51 int getgr(int l,int r,int rt,int x,int y,int z){ 52 int mid=(l+r)/2,res; 53 if (x<=l && r<=y){ 54 if (coltree[rt]==z) return l; 55 if (l==r) return -1; 56 if (coltree[rt*2+1]!=z) return getgr(mid+1,r,rt*2+1,x,y,z); 57 res=getgr(l,mid,rt*2,x,y,z); 58 return res==-1 ? mid+1 : res; 59 } 60 if (y<=mid) return getgr(l,mid,rt*2,x,y,z); 61 if (x>mid) return getgr(mid+1,r,rt*2+1,x,y,z); 62 res=getgr(mid+1,r,rt*2+1,x,y,z); 63 if (res==-1) return -1; 64 if (res>mid+1) return res; 65 res=getgr(l,mid,rt*2,x,y,z); 66 return res==-1 ? mid+1 : res; 67 } 68 int getans(int l,int r,int rt,int x,int y){ 69 if (l==r) return tree[y][rt]; 70 int mid=(l+r)/2; 71 pushdown(rt); 72 if (x<=mid) return getans(l,mid,rt*2,x,y); 73 else return getans(mid+1,r,rt*2+1,x,y); 74 } 75 void addtree(int l,int r,int rt,int x,int y,int z,int co){ 76 if (x<=l && r<=y) return (void)(tree[co][rt]+=z); 77 int mid=(l+r)/2; 78 pushdown(rt); 79 if (x<=mid) addtree(l,mid,rt*2,x,y,z,co); 80 if (mid<y) addtree(mid+1,r,rt*2+1,x,y,z,co); 81 } 82 void changecol(int l,int r,int rt,int x){ 83 if (l==r) return (void)(coltree[rt]^=1); 84 int mid=(l+r)/2; 85 if (x<=mid) changecol(l,mid,rt*2,x); 86 else changecol(mid+1,r,rt*2+1,x); 87 coltree[rt]=coltree[rt*2]==coltree[rt*2+1] ? coltree[rt*2] : -1; 88 } 89 90 int getfat(int t,int co){ 91 if (!fat[t][0] || col[fat[t][0]]!=co) return t; 92 int save=back[getgr(1,n,1,dfn[gr[t]],dfn[t],co)]; 93 if (save!=gr[t] || !fat[gr[t]][0] || col[fat[gr[t]][0]]!=co) return save; 94 else return getfat(fat[gr[t]][0],co); 95 } 96 void add(int co,int x,int y,int s){ 97 if (deep[x]>deep[y]) return; 98 if (gr[x]==gr[y]){ 99 addtree(1,n,1,dfn[x],dfn[y],s,co); 100 return; 101 } 102 addtree(1,n,1,dfn[gr[y]],dfn[y],s,co); 103 add(co,x,fat[gr[y]][0],s); 104 } 105 void change(int t){ 106 int p1=getans(1,n,1,dfn[t],col[t]),p2=getans(1,n,1,dfn[t],col[t]^1); 107 /*if (fat[t][0]){ 108 if (col[fat[t][0]]==col[t]) add(col[t]^1,fat[t][0],fat[t][0],p2); 109 else add(col[t],fat[t][0],fat[t][0],-p1); 110 }*/ 111 int fa=getfat(t,col[t]); 112 if (fat[fa][0]) fa=fat[fa][0]; 113 add(col[t],fa,fat[t][0],-p1); 114 col[t]^=1; 115 changecol(1,n,1,dfn[t]); 116 fa=getfat(t,col[t]); 117 if (fat[fa][0]) fa=fat[fa][0]; 118 add(col[t],fa,fat[t][0],p2); 119 } 120 int main(){ 121 freopen("spoj16549.in","r",stdin); 122 freopen("spoj16549.out","w",stdout); 123 scanf("%d",&n); 124 for (int x,y,i=1;i<n;i++){ 125 scanf("%d%d",&x,&y); 126 line[++nl]=inli(son[x],y),son[x]=nl; 127 line[++nl]=inli(son[y],x),son[y]=nl; 128 } 129 deep[1]=1; 130 makehard(1); 131 dfs(1,1); 132 build(1,n,1); 133 scanf("%d",&m); 134 for (int x,y,i=1;i<=m;i++){ 135 scanf("%d%d",&x,&y); 136 if (i==2) 137 i=2; 138 if (x) change(y); 139 else printf("%d\n",getans(1,n,1,dfn[getfat(y,col[y])],col[y])); 140 } 141 fclose(stdin); 142 fclose(stdout); 143 }
题意:
给出一颗点为黑色或白色的带点权的树
两个操作:
1.修改点的颜色
2.修改点权
一个询问:
求点与x相连的点的最大点权 两点相连条是这两点的路径上的点都与点x的颜色相同
把黑点和白点建成两颗树 同色的相连点就在同一颗树上
用set维护某点的轻边子树的最大值(取每个轻边子树的最大点权存进set)
再用动态树splay维护重边上的点最大值
询问时把该点access到根 再splay求出答案即可
access的时候要注意 当修改重边时 set要删除原轻边的最大值 加上原重边的最大值
修改点权也很好处理 - -稍微想想就知道了
修改颜色 则需要从某颜色的树上cut下一个点 再在另外颜色的树上link上一个点
但是当图为菊花图时link上的点的轻边个数可能有O(n)个 在set上一个个插入 一次操作就需要O(nlogn) 显然tle
orz神ak想到一种特别好的方法
在黑数上如果某点有个儿子的颜色为黑色就保留该点 白树同理 这样每次修改在set上就只会插入或删除一个点 就能过了
代码:
1 #include <cstdio> 2 #include <set> 3 using namespace std; 4 const int N=100001; 5 struct intr{ 6 int fat,lc,rc,t,max,root; 7 intr(const int a=0,const int b=0,const int c=0,const int d=0,const int e=0,const int f=1): 8 fat(a),lc(b),rc(c),t(d),max(e),root(f){} 9 }; 10 struct inli{ 11 int next,data; 12 inli(const int a=0,const int b=0): 13 next(a),data(b){} 14 }line[N*2]; 15 int n,m,nl,son[N],col[N],fat[N]; 16 int max(int x,int y){ return x>y ? x : y; } 17 struct LCT{ 18 intr tree[N]; 19 int xx; 20 multiset <int> se[N]; 21 void clean(){ tree[0]=intr(); } 22 void maintain(int t){ 23 tree[t].max=tree[t].t; 24 if (se[t].size()) tree[t].max=max(tree[t].max,*se[t].rbegin()); 25 if (tree[t].lc) tree[t].max=max(tree[t].max,tree[tree[t].lc].max); 26 if (tree[t].rc) tree[t].max=max(tree[t].max,tree[tree[t].rc].max); 27 } 28 void left(int t){ 29 int fa=tree[t].fat,r=tree[t].rc; 30 tree[t].rc=tree[r].lc,tree[tree[r].lc].fat=t; 31 tree[r].lc=t,tree[t].fat=r; 32 if (tree[t].root) tree[t].root=0,tree[r].root=1; 33 else if (tree[fa].lc==t) tree[fa].lc=r; 34 else tree[fa].rc=r; 35 tree[r].fat=fa; 36 clean(); 37 maintain(t); 38 maintain(r); 39 } 40 void right(int t){ 41 int fa=tree[t].fat,l=tree[t].lc; 42 tree[t].lc=tree[l].rc,tree[tree[l].rc].fat=t; 43 tree[l].rc=t,tree[t].fat=l; 44 if (tree[t].root) tree[t].root=0,tree[l].root=1; 45 else if (tree[fa].lc==t) tree[fa].lc=l; 46 else tree[fa].rc=l; 47 tree[l].fat=fa; 48 clean(); 49 maintain(t); 50 maintain(l); 51 } 52 void splay(int t){ 53 while (!tree[t].root){ 54 int fa=tree[t].fat,gr=tree[fa].fat; 55 if (tree[fa].root){ 56 if (tree[fa].lc==t) right(fa); 57 else left(fa); 58 }else if (tree[gr].lc==fa){ 59 if (tree[fa].lc==t) right(gr),right(fa); 60 else left(fa),right(gr); 61 }else if (tree[fa].rc==t) left(gr),left(fa); 62 else right(fa),left(gr); 63 } 64 } 65 66 void access(int t){ 67 xx=1; 68 for (int x=0,y=t;y;x=y,y=tree[y].fat){ 69 //Wa: no(x=y) y=fat[y]; 70 splay(y); 71 if (x) se[y].erase(tree[x].max); 72 if (tree[y].rc) se[y].insert(tree[tree[y].rc].max); 73 tree[x].root=0; 74 tree[tree[y].rc].root=1; 75 // no (tree[tree[y].rc].root=1;) 76 tree[y].rc=x; 77 clean(); 78 maintain(y); 79 } 80 } 81 int getl(int t){ 82 while (tree[t].lc) t=tree[t].lc; 83 return t; 84 } 85 int getans(int t){ 86 access(t); 87 splay(t); 88 int root=getl(t); 89 splay(root); 90 return col[root]==col[t] ? tree[root].max : tree[tree[root].rc].max; 91 // wa:tree[t].max 92 } 93 void changenum(int t,int s){ 94 access(t); 95 splay(t); 96 tree[t].t=s; 97 maintain(t); 98 } 99 void cut(int t){ 100 access(t); 101 splay(t); 102 tree[tree[t].lc].fat=0; 103 tree[tree[t].lc].root=1; 104 tree[t].lc=0; 105 maintain(t); 106 } 107 void link(int x,int y){ 108 splay(x); 109 access(y); 110 splay(y); 111 tree[x].fat=y; 112 se[y].insert(tree[x].max); 113 maintain(y); 114 } 115 }lct[2]; 116 void dfs(int t){ 117 if (fat[t]) lct[col[t]].tree[t].fat=fat[t]; 118 for (int i=son[t];i;i=line[i].next) 119 if (line[i].data!=fat[t]){ 120 int ne=line[i].data; 121 fat[ne]=t; 122 dfs(ne); 123 lct[col[ne]].se[t].insert(lct[col[ne]].tree[ne].max); 124 } 125 lct[0].maintain(t); 126 lct[1].maintain(t); 127 } 128 void changecol(int t){ 129 if (fat[t]){ 130 lct[col[t]].cut(t); 131 lct[col[t]^1].link(t,fat[t]); 132 } 133 col[t]^=1; 134 } 135 int main(){ 136 freopen("spoj16580.in","r",stdin); 137 freopen("spoj16580.out","w",stdout); 138 scanf("%d",&n); 139 for (int x,y,i=1;i<n;i++){ 140 scanf("%d%d",&x,&y); 141 line[++nl]=inli(son[x],y),son[x]=nl; 142 line[++nl]=inli(son[y],x),son[y]=nl; 143 } 144 for (int i=1;i<=n;i++) scanf("%d",&col[i]); 145 for (int x,i=1;i<=n;i++){ 146 scanf("%d",&x); 147 lct[0].tree[i].t=lct[0].tree[i].max=x; 148 lct[1].tree[i].t=lct[1].tree[i].max=x; 149 } 150 dfs(1); 151 scanf("%d",&m); 152 for (int x,y,z,i=1;i<=m;i++){ 153 scanf("%d%d",&x,&y); 154 if (i==3) 155 i=3; 156 if (x==0) printf("%d\n",lct[col[y]].getans(y)); 157 if (x==1) changecol(y); 158 if (x==2){ 159 scanf("%d",&z); 160 lct[0].changenum(y,z); 161 lct[1].changenum(y,z); 162 } 163 } 164 fclose(stdin); 165 fclose(stdout); 166 }