学习链接
BZOJ1935 园丁的烦恼
思路
对于每个查询查分成四个分别进行计数。三维分别为时间、\(x\)、\(y\),分治时间,归并\(x\),树状数组\(y\)。
代码
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 500000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
const int MX = 10000007;
int n, q, tot;
int ans[maxn], tree[MX];
int x, y, xx, yy;
struct node {
int op, x, y, c, qid;
}a[maxn*5];
void add(int x, int val) {
while(x < MX) {
tree[x] += val;
x += lowbit(x);
}
}
int ask(int x) {
int ans = 0;
while(x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
bool cmp(node a, node b) {
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
void CDQ(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
CDQ(l, mid); CDQ(mid + 1, r);
int ls = l;
for(int rs = mid + 1; rs <= r; ++rs) {
if(a[rs].op == 2) {
for( ; ls <= mid && a[ls].x <= a[rs].x; ++ls) {
if(a[ls].op == 1) add(a[ls].y, a[ls].c);
}
ans[a[rs].qid] += a[rs].c * ask(a[rs].y);
}
}
--ls;
while(ls >= l) {
if(a[ls].op == 1) add(a[ls].y, -1);
--ls;
}
inplace_merge(a + l, a + mid + 1, a + r + 1, cmp);
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; ++i) {
scanf("%d%d", &x, &y);
++x, ++y;
a[++tot] = {1, x, y, 1, 0};
}
for(int i = 1; i <= q; ++i) {
scanf("%d%d%d%d", &x, &y, &xx, &yy);
++x, ++y, ++xx, ++yy;
a[++tot] = {2, xx, yy, 1, i};
a[++tot] = {2, x - 1, yy, -1, i};
a[++tot] = {2, xx, y - 1, -1, i};
a[++tot] = {2, x - 1, y - 1, 1, i};
}
CDQ(1, tot);
for(int i = 1; i <= q; ++i) printf("%d\n", ans[i]);
return 0;
}
BZOJ1176 Mokia
思路
在上面的基础上改成了动态加点,但是处理方式其实是一样的,题目里面的\(s\)是没有用的。
代码
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 2000000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int w, tot, id, op, x, y, xx, yy, val;
int tree[maxn], ans[maxn];
struct node {
int x, y, op, c, id;
bool operator < (const node& a) const {
return x == a.x ? y < a.y : x < a.x;
}
}a[maxn];
void add(int x, int val) {
while(x <= w) {
tree[x] += val;
x += lowbit(x);
}
}
int ask(int x) {
int ans = 0;
while(x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
void cdq(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid), cdq(mid + 1, r);
int ls = l, rs = mid + 1;
for( ; rs <= r; ++rs) {
if(a[rs].op == 2) {
for( ; ls <= mid && a[ls].x <= a[rs].x; ++ls) {
if(a[ls].op == 1) add(a[ls].y, a[ls].c);
}
ans[a[rs].id] += a[rs].c * ask(a[rs].y);
}
}
--ls;
while(ls >= l) {
if(a[ls].op == 1) add(a[ls].y, -a[ls].c);
--ls;
}
inplace_merge(a + l, a + mid + 1, a + r + 1);
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%*d%d", &w);
while(1) {
scanf("%d", &op);
if(op == 3) break;
if(op == 1) {
scanf("%d%d%d", &x, &y, &val);
a[++tot] = {x, y, 1, val, 0};
} else {
scanf("%d%d%d%d", &x, &y, &xx, &yy);
++id;
a[++tot] = {x - 1, y - 1, 2, 1, id};
a[++tot] = {x - 1, yy, 2, -1, id};
a[++tot] = {xx, y - 1, 2, -1, id};
a[++tot] = {xx, yy, 2, 1, id};
}
}
cdq(1, tot);
for(int i = 1; i <= id; ++i) printf("%d\n", ans[i]);
return 0;
}
陌上花开
思路
三维偏序,在进行\(cdq\)分治之前需要将相同的进行合并,最后对于相同的花(假设是\(v\)),那么对于\(v\)的等级要加上\(cnt[v]-1\)。三维分别为\(a,b,c\),分治\(a\),归并\(b\),树状数组\(c\)。
代码
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 200000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int n, k, tot;
int tree[maxn], ans[maxn];
struct node {
int a, b, c, cnt, ans;
}tmp[maxn], num[maxn];
bool cmp1(node x, node y) {
return x.a != y.a ? x.a < y.a : x.b != y.b ? x.b < y.b : x.c < y.c;
}
bool cmp2(node x, node y) {
return x.b != y.b ? x.b < y.b : x.c < y.c;
}
void add(int x, int val) {
while(x <= k) {
tree[x] += val;
x += lowbit(x);
}
}
int ask(int x) {
int ans = 0;
while(x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
void cdq(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid), cdq(mid + 1, r);
int ls = l, rs = mid + 1;
while(ls <= mid && rs <= r) {
if(num[ls].b <= num[rs].b) {
add(num[ls].c, num[ls].cnt);
++ls;
} else {
num[rs].ans += ask(num[rs].c);
++rs;
}
}
while(rs <= r) {
num[rs].ans += ask(num[rs].c);
++rs;
}
--ls;
while(ls >= l) {
add(num[ls].c, -num[ls].cnt);
--ls;
}
inplace_merge(num + l, num + mid + 1, num + r + 1, cmp2);
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++i) {
scanf("%d%d%d", &tmp[i].a, &tmp[i].b, &tmp[i].c);
}
sort(tmp + 1, tmp + n + 1, cmp1);
num[++tot] = tmp[1];
num[tot].cnt = 1;
num[tot].ans = 0;
for(int i = 2; i <= n; ++i) {
if(tmp[i].a == num[tot].a && tmp[i].b == num[tot].b && tmp[i].c == num[tot].c) {
++num[tot].cnt, num[tot].ans = 0;
} else {
num[++tot] = tmp[i];
num[tot].cnt = 1;
num[tot].ans = 0;
}
}
cdq(1, tot);
for(int i = 1; i <= tot; ++i) {
ans[num[i].cnt-1+num[i].ans] += num[i].cnt;
}
for(int i = 0; i < n; ++i) {
printf("%d\n", ans[i]);
}
return 0;
}
BZOJ3295 动态逆序对
思路
我们先跑出原序列的逆序对,然后用\(cdq\)来计算出删除这个数逆序对的变化值,三维分别为时间、位置、值,分治时间,归并位置,树状数组值。
代码
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 100000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int n, m, x, tot;
LL sum;
int num[maxn], tree[maxn], vis[maxn];
LL ans[maxn];
struct node {
int x, tim;
}a[maxn], tmp[maxn];
void add(int x, int val, int n) {
while(x <= n) {
tree[x] += val;
x += lowbit(x);
}
}
int ask(int x) {
int ans = 0;
while(x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
void cdq(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid), cdq(mid + 1, r);
int cnt = 0, ls = mid, rs = r;
for(; rs >= mid + 1; --rs) {
for(; ls >= l && a[ls].x > a[rs].x; --ls) {
add(a[ls].tim, 1, m + 1);
++cnt;
}
if(a[rs].tim != m + 1) ans[a[rs].tim] += cnt - ask(a[rs].tim);
}
++ls;
while(ls <= mid) {
add(a[ls].tim, -1, m + 1);
++ls;
}
cnt = 0, ls = l, rs = mid + 1;
for(; ls <= mid; ++ls) {
for(; rs <= r && a[rs].x < a[ls].x; ++rs) {
add(a[rs].tim, 1, m + 1);
++cnt;
}
if(a[ls].tim != m + 1) ans[a[ls].tim] += cnt - ask(a[ls].tim);
}
--rs;
while(rs >= mid + 1) {
add(a[rs].tim, -1, m + 1);
--rs;
}
cnt = ls = l, rs = mid + 1;
while(ls <= mid && rs <= r) {
if(a[ls].x < a[rs].x) {
tmp[cnt++] = a[ls++];
} else {
tmp[cnt++] = a[rs++];
}
}
while(ls <= mid) {
tmp[cnt++] = a[ls++];
}
while(rs <= r) {
tmp[cnt++] = a[rs++];
}
for(int i = l; i <= r; ++i) a[i] = tmp[i];
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) {
scanf("%d", &num[i]);
a[++tot] = {num[i], m + 1};
vis[num[i]] = tot;
}
for(int i = 1; i <= m; ++i) {
scanf("%d", &x);
a[vis[x]].tim = i;
}
for(int i = 1; i <= n; ++i) {
sum += i - 1 - ask(num[i]);
add(num[i], 1, n);
}
for(int i = 1; i <= n; ++i) {
add(num[i], -1, n);
}
cdq(1, n);
for(int i = 1; i <= m; ++i) {
printf("%lld\n", sum);
sum -= ans[i];
}
return 0;
}
HDU5324 Boring Class
思路
三维分别是位置、\(L\)、\(R\),分治位置,归并\(R\),树状数组\(L\)。
由于需要输出字典序最小的方案,因此我们考虑在合并的时候用右边来更新左边的信息,记录每个位置作为\(v_1\)能选出的最大的\(m\)。
代码
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("/home/dillonh/CLionProjects/Dillonh/in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 50000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
int n, sz;
vector<int> vec;
int L[maxn], R[maxn], tree[maxn], ans[maxn];
struct node {
int pos, x, y;
bool operator < (const node& a) const {
return y > a.y;
}
}a[maxn];
void add(int x, int val) {
while(x <= sz) {
tree[x] = max(tree[x], val);
x += lowbit(x);
}
}
void del(int x) {
while(x <= sz) {
tree[x] = 0;
x += lowbit(x);
}
}
int ask(int x) {
int ans = 0;
while(x) {
ans = max(ans, tree[x]);
x -= lowbit(x);
}
return ans;
}
bool cmp(node a, node b) {
return a.pos < b.pos;
}
void cdq(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
cdq(mid + 1, r);
sort(a + l, a + mid + 1);
sort(a + mid + 1, a + r + 1);
int ls = l, rs = mid + 1;
for(; ls <= mid; ++ls) {
for(; rs <= r && a[rs].y >= a[ls].y; ++rs) {
add(a[rs].x, ans[a[rs].pos]);
}
ans[a[ls].pos] = max(ans[a[ls].pos], ask(a[ls].x) + 1);
}
--rs;
while(rs >= l) {
del(a[rs].x);
--rs;
}
sort(a + l, a + mid + 1, cmp);
cdq(l, mid);
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
while(~scanf("%d", &n)) {
vec.clear();
for(int i = 1; i <= n; ++i) scanf("%d", &L[i]), a[i].x = L[i], a[i].pos = i, vec.emplace_back(L[i]);
for(int i = 1; i <= n; ++i) scanf("%d", &R[i]), a[i].y = R[i], ans[i] = 1;
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
for(int i = 1; i <= n; ++i) a[i].x = lower_bound(vec.begin(), vec.end(), a[i].x) - vec.begin() + 1;
sz = vec.size();
cdq(1, n);
int mx = 0, idx = 1;
for(int i = 1; i <= n; ++i) {
if(ans[i] > mx) {
mx = ans[i];
idx = i;
}
}
int las = L[idx], lst = R[idx];
vec.clear();
vec.emplace_back(idx);
for(int i = idx + 1; i <= n; ++i) {
if(ans[i] == mx - 1 && L[i] <= las && R[i] >= lst) {
mx = ans[i], las = L[i], lst = R[i];
vec.emplace_back(i);
}
}
printf("%d\n", (int)vec.size());
for(int i = 0; i < (int)vec.size(); ++i) {
if(i) printf(" ");
printf("%d", vec[i]);
}
printf("\n");
}
return 0;
}
HDU5126 stars
思路
四维偏序,分别为时间,\(x,y,z\),分治时间和\(x\),归并\(x,y\),树状数组\(z\)。
注意第二个\(cdq\)不能改变第一个的数组位置,在第一个\(cdq\)时需要标记每个数组在该分治中是左边一半还是右边一半,如果不标记的话那么在第二次\(cdq\)时就会忽略时间的关系。
代码
#include <set>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <bitset>
#include <cstdio>
#include <string>
#include <vector>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<LL, LL> pLL;
typedef pair<LL, int> pLi;
typedef pair<int, LL> pil;;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) x&(-x)
#define name2str(name) (#name)
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
#define FIN freopen("D://Code//in.txt","r",stdin)
#define IO ios::sync_with_stdio(false),cin.tie(0)
const double eps = 1e-8;
const int mod = 1000000007;
const int maxn = 450000 + 7;
const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
vector<int> vec;
int t, q, tot, op, x, y, z, xx, yy, zz, sz;
int tree[maxn], ans[maxn];
struct node {
int x, y, z, op, id, flag, c;
}a[maxn], tmp[maxn], pp[maxn];
void add(int x, int val) {
while(x <= sz) {
tree[x] += val;
x += lowbit(x);
}
}
int ask(int x) {
int ans = 0;
while(x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
void cdq2(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
cdq2(l, mid), cdq2(mid + 1, r);
int ls = l, rs = mid + 1, cnt = l;
for(; rs <= r; ++rs) {
for(; ls <= mid && tmp[ls].y <= tmp[rs].y; ++ls) {
if(tmp[ls].op == 1 && tmp[ls].flag) add(tmp[ls].z, tmp[ls].c);
}
if(tmp[rs].op == 2 && !tmp[rs].flag) ans[tmp[rs].id] += tmp[rs].c * ask(tmp[rs].z);
}
--ls;
while(ls >= l) {
if(tmp[ls].op == 1 && tmp[ls].flag) add(tmp[ls].z, -tmp[ls].c);
--ls;
}
ls = l, rs = mid + 1;
while(ls <= mid && rs <= r) {
if(tmp[ls].y < tmp[rs].y) {
pp[cnt++] = tmp[ls++];
} else if(tmp[ls].y > tmp[rs].y) {
pp[cnt++] = tmp[rs++];
} else if(tmp[ls].z <= tmp[rs].z) {
pp[cnt++] = tmp[ls++];
} else {
pp[cnt++] = tmp[rs++];
}
}
while(ls <= mid) {
pp[cnt++] = tmp[ls++];
}
while(rs <= r) {
pp[cnt++] = tmp[rs++];
}
for(int i = l; i <= r; ++i) tmp[i] = pp[i];
}
void cdq1(int l, int r) {
if(l == r) return;
int mid = (l + r) >> 1;
cdq1(l, mid); cdq1(mid + 1, r);
int ls = l, rs = mid + 1, cnt = l;
while(ls <= mid && rs <= r) {
if(a[ls].x < a[rs].x) {
tmp[cnt] = a[ls++];
tmp[cnt++].flag = 1;
} else if(a[ls].x > a[rs].x) {
tmp[cnt] = a[rs++];
tmp[cnt++].flag = 0;
} else if(a[ls].y < a[rs].y) {
tmp[cnt] = a[ls++];
tmp[cnt++].flag = 1;
} else if(a[ls].y > a[rs].y) {
tmp[cnt] = a[rs++];
tmp[cnt++].flag = 0;
} else if(a[ls].z <= a[rs].z) {
tmp[cnt] = a[ls++];
tmp[cnt++].flag = 1;
} else {
tmp[cnt] = a[rs++];
tmp[cnt++].flag = 0;
}
}
while(ls <= mid) {
tmp[cnt] = a[ls++];
tmp[cnt++].flag = 1;
}
while(rs <= r) {
tmp[cnt] = a[rs++];
tmp[cnt++].flag = 0;
}
for(int i = l; i <= r; ++i) a[i] = tmp[i];
cdq2(l, r);
}
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
scanf("%d", &t);
while(t--) {
tot = 0;
vec.clear();
scanf("%d", &q);
int cnt = 0;
for(int i = 1; i <= q; ++i) {
scanf("%d%d%d%d", &op, &x, &y, &z);
if(op == 1) a[++tot] = {x, y, z, op, 0, 0, 1}, vec.push_back(z);
else {
scanf("%d%d%d", &xx, &yy, &zz);
++cnt;
a[++tot] = {xx, yy, zz, op, cnt, 0, 1};
a[++tot] = {x - 1, yy, zz, op, cnt, 0, -1};
a[++tot] = {xx, y - 1, zz, op, cnt, 0, -1};
a[++tot] = {xx, yy, z - 1, op, cnt, 0, -1};
a[++tot] = {x - 1, y - 1, zz, op, cnt, 0, 1};
a[++tot] = {x - 1, yy, z - 1, op, cnt, 0, 1};
a[++tot] = {xx, y - 1, z - 1, op, cnt, 0, 1};
a[++tot] = {x - 1, y - 1, z - 1, op, cnt, 0, -1};
vec.push_back(z); vec.push_back(z - 1);
vec.push_back(zz); vec.push_back(zz - 1);
}
}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
sz = vec.size();
for(int i = 1; i <= tot; ++i) {
a[i].z = lower_bound(vec.begin(), vec.end(), a[i].z) - vec.begin() + 1;
}
cdq1(1, tot);
for(int i = 1; i <= cnt; ++i) {
printf("%d\n", ans[i]);
ans[i] = 0;
}
}
return 0;
}