新的一周>.<
6.27
leetcode 99 Recover Binary Search Tree
一颗二叉搜索树有两个节点的位置不对,让把这两个位置换回来
中序遍历的二叉搜索树是升序排列的,所以在中序遍历的时候,记录下这两个节点就好
1 class Solution{ 2 public: 3 TreeNode* p1; 4 TreeNode* p2; 5 TreeNode* pre; 6 void recoverTree(TreeNode* root){ 7 inorder(root); 8 if(p1 != NULL && p2 != NULL){ 9 swap(p1->val,p2->val); 10 } 11 } 12 13 void inorder(TreeNode* root){ 14 if(root == NULL) return; 15 if(root->left != NULL) inorder(root->left); 16 if(pre != NULL && pre->val > root->val){ 17 if(p1 == NULL){ 18 p1 = pre; 19 p2 = root; 20 } 21 else p2 = root; 22 } 23 pre = root; 24 if(root->right != NULL) inorder(root->right); 25 } 26 };
6.28
好颓啊...upupupup起来
srm 693div2 250
真正意义上的第一次在tc上面做题目
...在朋友圈发了个tc的截图,让青蛙以为是 tc 的老司机...........sigh..........
可是是一个不会写类,不会看题,不会提交,的彩笔
在青蛙的帮助下,装上了greed插件,并成功ac了第一道题
感谢!!!
原来 比赛 和 练习的目录是不一样的...sigh...
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 #include <ctime> 5 #include <iostream> 6 #include <algorithm> 7 #include <set> 8 #include <vector> 9 #include <sstream> 10 #include <typeinfo> 11 #include <fstream> 12 13 using namespace std; 14 15 class TriangleEasy { 16 public: 17 int find(int n, vector<int> x, vector<int> y) { 18 int g[55][55],d[55]; 19 memset(g,0,sizeof(g)); 20 memset(d,0,sizeof(d)); 21 if(x.size() == 0) return 3; 22 for(int i = 0;i < x.size();i++){ 23 int u = x[i]; 24 int v = y[i]; 25 g[u][v] = 1;g[v][u] = 1; 26 d[u]++;d[v]++; 27 } 28 for(int i = 0;i < n;i++){ 29 for(int j = i+1;j < n;j++){ 30 for(int k = j+1;k < n;k++){ 31 if(g[i][j] && g[j][k] && g[k][i]) return 0; 32 } 33 } 34 } 35 for(int i = 0;i < n;i++) if(d[i] >= 2) return 1; 36 return 2; 37 } 38 }; 39 40 // CUT begin 41 ifstream data("TriangleEasy.sample"); 42 43 string next_line() { 44 string s; 45 getline(data, s); 46 return s; 47 } 48 49 template <typename T> void from_stream(T &t) { 50 stringstream ss(next_line()); 51 ss >> t; 52 } 53 54 void from_stream(string &s) { 55 s = next_line(); 56 } 57 58 template <typename T> void from_stream(vector<T> &ts) { 59 int len; 60 from_stream(len); 61 ts.clear(); 62 for (int i = 0; i < len; ++i) { 63 T t; 64 from_stream(t); 65 ts.push_back(t); 66 } 67 } 68 69 template <typename T> 70 string to_string(T t) { 71 stringstream s; 72 s << t; 73 return s.str(); 74 } 75 76 string to_string(string t) { 77 return "\"" + t + "\""; 78 } 79 80 bool do_test(int n, vector<int> x, vector<int> y, int __expected) { 81 time_t startClock = clock(); 82 TriangleEasy *instance = new TriangleEasy(); 83 int __result = instance->find(n, x, y); 84 double elapsed = (double)(clock() - startClock) / CLOCKS_PER_SEC; 85 delete instance; 86 87 if (__result == __expected) { 88 cout << "PASSED!" << " (" << elapsed << " seconds)" << endl; 89 return true; 90 } 91 else { 92 cout << "FAILED!" << " (" << elapsed << " seconds)" << endl; 93 cout << " Expected: " << to_string(__expected) << endl; 94 cout << " Received: " << to_string(__result) << endl; 95 return false; 96 } 97 } 98 99 int run_test(bool mainProcess, const set<int> &case_set, const string command) { 100 int cases = 0, passed = 0; 101 while (true) { 102 if (next_line().find("--") != 0) 103 break; 104 int n; 105 from_stream(n); 106 vector<int> x; 107 from_stream(x); 108 vector<int> y; 109 from_stream(y); 110 next_line(); 111 int __answer; 112 from_stream(__answer); 113 114 cases++; 115 if (case_set.size() > 0 && case_set.find(cases - 1) == case_set.end()) 116 continue; 117 118 cout << " Testcase #" << cases - 1 << " ... "; 119 if ( do_test(n, x, y, __answer)) { 120 passed++; 121 } 122 } 123 if (mainProcess) { 124 cout << endl << "Passed : " << passed << "/" << cases << " cases" << endl; 125 int T = time(NULL) - 1467072843; 126 double PT = T / 60.0, TT = 75.0; 127 cout << "Time : " << T / 60 << " minutes " << T % 60 << " secs" << endl; 128 cout << "Score : " << 250 * (0.3 + (0.7 * TT * TT) / (10.0 * PT * PT + TT * TT)) << " points" << endl; 129 } 130 return 0; 131 } 132 133 int main(int argc, char *argv[]) { 134 cout.setf(ios::fixed, ios::floatfield); 135 cout.precision(2); 136 set<int> cases; 137 bool mainProcess = true; 138 for (int i = 1; i < argc; ++i) { 139 if ( string(argv[i]) == "-") { 140 mainProcess = false; 141 } else { 142 cases.insert(atoi(argv[i])); 143 } 144 } 145 if (mainProcess) { 146 cout << "TriangleEasy (250 Points)" << endl << endl; 147 } 148 return run_test(mainProcess, cases, argv[0]); 149 } 150 // CUT end
6.29
cdoj 1328 卿学姐与诡异村庄
并查集
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int maxn = 5e5+5; 8 int fa[maxn],n; 9 10 int Find(int x){return x == fa[x]?x : fa[x] = Find(fa[x]);} 11 12 int good(int x) {return x;} 13 14 int bad(int x){return x+n;} 15 16 void Union(int u,int v){ 17 int x = Find(u); 18 int y = Find(v); 19 if(x != y) fa[x] = y; 20 } 21 22 void solve(){ 23 for(int i = 1;i <= n;i++){ 24 int x = Find(good(i)); 25 int y = Find(bad(i)); 26 if(x == y){ 27 puts("One face meng bi"); 28 return; 29 } 30 } 31 puts("Time to show my power"); 32 } 33 34 int main(){ 35 while(scanf("%d",&n) != EOF){ 36 for(int i = 1;i <= 2*n;i++) fa[i] = i; 37 int u,v; 38 for(int i = 1;i <= n;i++){ 39 scanf("%d %d",&u,&v); 40 if(v == 1){ 41 Union(good(u),good(i)); 42 Union(bad(u),bad(i)); 43 } 44 else{ 45 Union(good(u),bad(i)); 46 Union(bad(u),good(i)); 47 } 48 } 49 solve(); 50 } 51 return 0; 52 }
cdoj 1329 卿学姐与魔法
在5月份的时候贪心写错了,一直没有补..真是懒成 dog了..0-0
今天看了题解..
感觉很关键的一句话 是
“我们尝试去维护一个集合,这个集合一定能够包含我们当前需要的最小值。”
然后就用堆来维护
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 8 const int maxn = 1e5+5; 9 int a[maxn],b[maxn],n,ans[maxn]; 10 11 struct node{ 12 int x,y; 13 friend bool operator < (node n1,node n2){ 14 return a[n1.x]+b[n1.y] > a[n2.x]+b[n2.y]; 15 } 16 }; 17 18 void solve(){ 19 sort(a+1,a+n+1); 20 sort(b+1,b+n+1); 21 priority_queue<node> q; 22 for(int i = 1;i <= n;i++){ 23 q.push((node){i,1}); 24 } 25 int cc = 0; 26 for(int i = 1;i <= n;i++){ 27 node tmp = q.top();q.pop(); 28 ans[++cc] = a[tmp.x]+b[tmp.y]; 29 tmp.y++; 30 if(tmp.y == n+1) continue; 31 q.push(tmp); 32 //printf("tmp.x = %d tmp.y = %d\n",tmp.x,tmp.y); 33 } 34 for(int i = 1;i <= cc;i++) printf("%d\n",ans[i]); 35 } 36 37 int main(){ 38 while(scanf("%d",&n) != EOF){ 39 for(int i = 1;i <= n;i++) scanf("%d",&a[i]); 40 for(int i = 1;i <= n;i++) scanf("%d",&b[i]); 41 solve(); 42 } 43 return 0; 44 }
cdoj 1334 郭大侠与Rabi-Ribi
想法就没对..
想的是 每次查询一个区间的最大值,再把这个最大值改掉,维护后面区间的新的最大值
非常非常不对..
应该是用优先队列
在时间能够的情况下,把兔子丢进队列里面
在时间不够的情况下,就把value更大的兔子丢进去
.................感觉这样的做法好像以前在别的题目见过,但是想不起来了..
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 8 const int maxn = 1e5+5; 9 int a[maxn],b[maxn],n,ans[maxn]; 10 11 struct node{ 12 int x,y; 13 friend bool operator < (node n1,node n2){ 14 return a[n1.x]+b[n1.y] > a[n2.x]+b[n2.y]; 15 } 16 }; 17 18 void solve(){ 19 sort(a+1,a+n+1); 20 sort(b+1,b+n+1); 21 priority_queue<node> q; 22 for(int i = 1;i <= n;i++){ 23 q.push((node){i,1}); 24 } 25 int cc = 0; 26 for(int i = 1;i <= n;i++){ 27 node tmp = q.top();q.pop(); 28 ans[++cc] = a[tmp.x]+b[tmp.y]; 29 tmp.y++; 30 if(tmp.y == n+1) continue; 31 q.push(tmp); 32 //printf("tmp.x = %d tmp.y = %d\n",tmp.x,tmp.y); 33 } 34 for(int i = 1;i <= cc;i++) printf("%d\n",ans[i]); 35 } 36 37 int main(){ 38 while(scanf("%d",&n) != EOF){ 39 for(int i = 1;i <= n;i++) scanf("%d",&a[i]); 40 for(int i = 1;i <= n;i++) scanf("%d",&b[i]); 41 solve(); 42 } 43 return 0; 44 }
cdoj 383 Japan
树状数组求逆序对
忘记清空 c 数组,sbsbsbsb
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 const int maxn = 1e6+5; 9 int b[maxn],c[maxn]; 10 int n,m,k; 11 12 struct node{ 13 int x,y; 14 }a[maxn]; 15 16 int cmp(node a,node b){ 17 return a.x < b.x || (a.x == b.x && a.y < b.y); 18 } 19 20 int lowbit(int x) {return x & (-x);} 21 22 int sum(int x){ 23 int ret = 0; 24 while(x > 0){ 25 ret += c[x]; 26 x -= lowbit(x); 27 } 28 return ret; 29 } 30 31 void add(int x,int d){ 32 while(x <= maxn){ 33 c[x] += d; 34 x += lowbit(x); 35 } 36 } 37 38 LL solve(){ 39 sort(a+1,a+k+1,cmp); 40 LL ans = 0LL; 41 for(int i = 1;i <= k;i++){ 42 add(a[i].y,1); 43 int tmp = i-sum(a[i].y); 44 ans += 1LL*tmp; 45 } 46 return ans; 47 } 48 49 int main(){ 50 int T; 51 scanf("%d",&T); 52 int kase = 0; 53 while(T--){ 54 memset(c,0,sizeof(c)); 55 scanf("%d %d %d",&n,&m,&k); 56 for(int i = 1;i <= k;i++){ 57 scanf("%d %d",&a[i].x,&a[i].y); 58 } 59 LL ans = solve(); 60 printf("Test case %d: %lld\n", ++kase, ans); 61 } 62 return 0; 63 }
6.30
cf 360 div2 c NP-Hard Problem
判断二分图就可以了,但是 死在了一次 12组
因为 是 只要判断到一次不是二分图就得马上跳出来
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 8 const int maxn = 1e5+5; 9 int col[maxn],n,m; 10 vector<int> g[maxn]; 11 12 void print(){ 13 vector<int> lb,ub; 14 for(int i = 1;i <= n;i++){ 15 if(g[i].size() == 0) continue; 16 if(col[i] == 1) lb.push_back(i); 17 if(col[i] == -1) ub.push_back(i); 18 } 19 printf("%d\n",lb.size()); 20 for(int i = 0;i < lb.size();i++) printf("%d ",lb[i]); 21 printf("\n"); 22 printf("%d\n",ub.size()); 23 for(int i = 0;i < ub.size();i++) printf("%d ",ub[i]); 24 printf("\n"); 25 } 26 27 int dfs(int u,int c){ 28 col[u] = c; 29 for(int i = 0;i < g[u].size();i++){ 30 int v = g[u][i]; 31 if(col[v] == col[u]) return 0; 32 if(!col[v] && !dfs(v,-c)) return 0; 33 } 34 return 1; 35 } 36 37 void solve(){ 38 memset(col,0,sizeof(col)); 39 for(int i = 1;i <= n;i++){ 40 if(col[i] != 0) continue; 41 if(!dfs(i,1)){ 42 /* printf("i = %d\n",i); 43 for(int j = 1;j <= n;j++) printf("col[%d] = %d\n",j,col[j]);*/ 44 printf("-1\n"); 45 return; 46 } 47 } 48 print(); 49 } 50 51 int main(){ 52 while(scanf("%d %d",&n,&m) != EOF){ 53 for(int i = 1;i <= n;i++) g[i].clear(); 54 int u,v; 55 for(int i = 1;i <= m;i++){ 56 scanf("%d %d",&u,&v); 57 g[u].push_back(v); 58 g[v].push_back(u); 59 } 60 solve(); 61 } 62 return 0; 63 }
7.1
新的一个月了诶..
干巴爹TAT /
leetcode 100 Same Tree
判断两颗二叉树是否是形态和值都一样,递归做就可以了
1 class Solution{ 2 public: 3 bool isSameTree(TreeNode* p,TreeNode* q){ 4 if(p == NULL && q == NULL) return true; 5 if(p == NULL || q == NULL) return false; 6 if(p->val == q->Bval) { 7 return isSameTree(p->left,q->left) && isSameTree(p->right,q->right); 8 } 9 else return false; 10 } 11 };
leetcode 101 Symmetric Tree
判断一颗二叉树是不是镜面对称的
和上一题很像,看到有双端队列的写法
1 class Solution{ 2 public: 3 bool isSymmetric(TreeNode* root){ 4 if(root == NULL) return true; 5 return check(root->left,root->right); 6 } 7 8 bool check(TreeNode* p,TreeNode* q){ 9 if(p == NULL && q == NULL) return true; 10 if(p == NULL || q == NULL) return false; 11 if(p->val == q->val){ 12 return check(p->left,q->right) && check(p->right,q->left); 13 } 14 return false; 15 } 16 };
用双端队列来写的,先不是很理解,在纸上画了一颗二叉树,模拟了下懂一点点了
1 class Solution{ 2 public: 3 bool isSymmetric(TreeNode* root){ 4 if(root == NULL) return true; 5 6 deque<TreeNode*> dq; 7 dq.push_front(root->left); 8 dq.push_back(root->right); 9 10 TreeNode* p = NULL; 11 TreeNode* q = NULL; 12 13 while(!dq.empty()){ 14 p = dq.front();dq.pop_front(); 15 q = dq.back();dq.pop_back(); 16 if(p == NULL && q == NULL) continue; 17 if(p == NULL || q == NULL) return false; 18 if(p->val != q->val) return false; 19 else{ 20 dq.push_front(p->right); 21 dq.push_front(p->left); 22 dq.push_back(q->left); 23 dq.push_back(q->right); 24 } 25 } 26 return true; 27 } 28 };
cf 360 div2 e E - The Values You Can Make
从过题人数来看,是很水的dp了...可是还是不会捉..
瞅了一个下午的中国剩余定理,还是不懂d题..呜呜呜呜呜...智商捉鸡
能够组成 k 的集合还能够组成些啥数,输出 这些数
dp[i][j][k] 表示 前 i 个数 和为 j ,子集和为 k 是否可行
用 bool不会MLE
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 8 const int maxn = 505; 9 bool dp[maxn][maxn][maxn]; 10 int c[maxn],K,n; 11 12 void solve(){ 13 memset(dp,0,sizeof(dp)); 14 dp[0][0][0] = 1; 15 for(int i = 1;i <= n;i++){ 16 for(int j = 0;j <= 500;j++){ 17 for(int k = 0;k <= j;k++){ 18 dp[i][j][k] |= dp[i-1][j][k];//the i-th coin is not used in the ssubsets 19 if(j >= c[i]) dp[i][j][k] |= dp[i-1][j-c[i]][k];//the i-th coin is used in the subset to make j ,but it's not used in the subset of this subset 20 if(k >= c[i]) dp[i][j][k] |= dp[i-1][j-c[i]][k-c[i]];//the i-th coin is used in both subsets 21 } 22 } 23 } 24 vector<int> ans; 25 for(int i = 0;i <= 500;i++){ 26 if(dp[n][K][i]) ans.push_back(i); 27 } 28 printf("%d\n",ans.size()); 29 for(int i = 0;i < ans.size();i++) printf("%d ",ans[i]); 30 printf("\n"); 31 } 32 33 int main(){ 34 while(scanf("%d %d",&n,&K) != EOF){ 35 for(int i = 1;i <= n;i++) scanf("%d",&c[i]); 36 solve(); 37 } 38 return 0; 39 }
7.2
做..做..做 水题
每次找到最小的水龙头,在那儿排队等水就好
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int maxn = 1e4+5; 8 int a[maxn],s[maxn],n,m; 9 const int INF = (1<<30)-1; 10 11 int main(){ 12 scanf("%d %d",&n,&m); 13 for(int i = 1;i <= n;i++){ 14 scanf("%d",&a[i]); 15 } 16 memset(s,0,sizeof(s)); 17 for(int i = 1;i <= n;i++){ 18 int mn = INF,pos; 19 for(int j = 1;j <= m;j++){ 20 if(s[j] < mn){pos = j;mn = s[j];} 21 } 22 s[pos] += a[i]; 23 } 24 int mx = 0; 25 for(int i = 1;i <= m;i++){ 26 mx = max(mx,s[i]); 27 } 28 printf("%d\n",mx); 29 return 0; 30 }
7.3
一看到 n 的范围 就想 是 数位 dp 了,可是 dp 不出来
应该先打下表,再去想
1 #include <stdio.h> 2 #include <math.h> 3 #include <string.h> 4 #include <iostream> 5 #include <string> 6 #include <algorithm> 7 using namespace std; 8 9 const int numlen = 1e4+5; 10 11 int max(int a, int b) { return a>b?a:b; } 12 struct bign { 13 int len, s[numlen]; 14 bign() { 15 memset(s, 0, sizeof(s)); 16 len = 1; 17 } 18 bign(int num) { *this = num; } 19 bign(const char *num) { *this = num; } 20 bign operator = (const int num) { 21 char s[numlen]; 22 sprintf(s, "%d", num); 23 *this = s; 24 return *this; 25 } 26 bign operator = (const char *num) { 27 len = strlen(num); 28 while(len > 1 && num[0] == '0') num++, len--; 29 for(int i = 0;i < len; i++) s[i] = num[len-i-1] - '0'; 30 return *this; 31 } 32 33 void deal() { 34 while(len > 1 && !s[len-1]) len--; 35 } 36 37 bign operator + (const bign &a) const { 38 bign ret; 39 ret.len = 0; 40 int top = max(len, a.len) , add = 0; 41 for(int i = 0;add || i < top; i++) { 42 int now = add; 43 if(i < len) now += s[i]; 44 if(i < a.len) now += a.s[i]; 45 ret.s[ret.len++] = now%10; 46 add = now/10; 47 } 48 return ret; 49 } 50 bign operator - (const bign &a) const { 51 bign ret; 52 ret.len = 0; 53 int cal = 0; 54 for(int i = 0;i < len; i++) { 55 int now = s[i] - cal; 56 if(i < a.len) now -= a.s[i]; 57 if(now >= 0) cal = 0; 58 else { 59 cal = 1; now += 10; 60 } 61 ret.s[ret.len++] = now; 62 } 63 ret.deal(); 64 return ret; 65 } 66 bign operator * (const bign &a) const { 67 bign ret; 68 ret.len = len + a.len; 69 for(int i = 0;i < len; i++) { 70 for(int j = 0;j < a.len; j++) 71 ret.s[i+j] += s[i]*a.s[j]; 72 } 73 for(int i = 0;i < ret.len; i++) { 74 ret.s[i+1] += ret.s[i]/10; 75 ret.s[i] %= 10; 76 } 77 ret.deal(); 78 return ret; 79 } 80 81 //乘以小数,直接乘快点 82 bign operator * (const int num) { 83 bign ret; 84 ret.len = 0; 85 int bb = 0; 86 for(int i = 0;i < len; i++) { 87 int now = bb + s[i]*num; 88 ret.s[ret.len++] = now%10; 89 bb = now/10; 90 } 91 while(bb) { 92 ret.s[ret.len++] = bb % 10; 93 bb /= 10; 94 } 95 ret.deal(); 96 return ret; 97 } 98 99 bign operator / (const bign &a) const { 100 bign ret, cur = 0; 101 ret.len = len; 102 for(int i = len-1;i >= 0; i--) { 103 cur = cur*10; 104 cur.s[0] = s[i]; 105 while(cur >= a) { 106 cur -= a; 107 ret.s[i]++; 108 } 109 } 110 ret.deal(); 111 return ret; 112 } 113 114 bign operator % (const bign &a) const { 115 bign b = *this / a; 116 return *this - b*a; 117 } 118 119 bign operator += (const bign &a) { *this = *this + a; return *this; } 120 bign operator -= (const bign &a) { *this = *this - a; return *this; } 121 bign operator *= (const bign &a) { *this = *this * a; return *this; } 122 bign operator /= (const bign &a) { *this = *this / a; return *this; } 123 bign operator %= (const bign &a) { *this = *this % a; return *this; } 124 125 bool operator < (const bign &a) const { 126 if(len != a.len) return len < a.len; 127 for(int i = len-1;i >= 0; i--) if(s[i] != a.s[i]) 128 return s[i] < a.s[i]; 129 return false; 130 } 131 bool operator > (const bign &a) const { return a < *this; } 132 bool operator <= (const bign &a) const { return !(*this > a); } 133 bool operator >= (const bign &a) const { return !(*this < a); } 134 bool operator == (const bign &a) const { return !(*this > a || *this < a); } 135 bool operator != (const bign &a) const { return *this > a || *this < a; } 136 137 string str() const { 138 string ret = ""; 139 for(int i = 0;i < len; i++) ret = char(s[i] + '0') + ret; 140 return ret; 141 } 142 143 bign print(){ 144 for(int i = len-1;i >= 0;i--) printf("%d",s[i]); 145 } 146 }; 147 148 istream& operator >> (istream &in, bign &x) { 149 string s; 150 in >> s; 151 x = s.c_str(); 152 return in; 153 } 154 ostream& operator << (ostream &out, const bign &x) { 155 out << x.str(); 156 return out; 157 } 158 159 bign gcd(bign a, bign b) { 160 while(b != 0) { 161 bign tmp = a%b; 162 a = b; b = tmp; 163 } 164 return a; 165 } 166 167 bign a,b,c; 168 169 int n; 170 171 int main() { 172 cin >> a; 173 b = 3; 174 if(a%3 == 0){ 175 b = a/3; 176 b.print();printf(" "); 177 b.print();printf(" "); 178 b.print();printf("\n"); 179 } 180 else puts("-1"); 181 return 0; 182 }
一点都不会网络流了..
我好菜啊.....................................................