POJ-3368

来源:互联网 发布:伴读软件 编辑:程序博客网 时间:2024/06/08 16:25

长舒了一口气,这题搞了我一天,最后终于搞出来了,好爽!!虽然这种对于大牛们来说是线段树的水题,但是我这种菜菜就要弄好久。。还好最后A了,中间尝试着用书上的平方分割的方法写,T了。。我最后对了对标准输出结果应该是对的,但是效率太差没办法,只能全部推倒重写。。我的思路是把连续相同数的弄成一个区间,记录左右端点和区间内的最大连续值,构树,然后利用线段树来查

#include<cstdio>#include<vector>#include<algorithm>using namespace std;namespace{int n, q, a, b, N;vector<int> V;const int MAX_N = (1 << 17) - 1;struct Node{int l, r, d;} dat[MAX_N];void build(int k){int left = 2 * k + 1;int right = 2 * k + 2;if (left < N - 1){build(left);build(right);}dat[k].l = dat[left].l;dat[k].r = dat[right].r;dat[k].d = max(dat[left].d, dat[right].d);}void init(){N = 1;int size = V.size();while (N < size)N <<= 1;for (size_t i = 0; i < V.size(); i++){int index = i + N - 1;dat[index].l = V[i];dat[index].r = i + 1 < V.size() ? V[i + 1] : n;dat[index].d = dat[index].r - dat[index].l;}for (int i = V.size() + N - 1; i < 2 * N - 1; i++){dat[i].l = dat[i].r = n;dat[i].d = 0;}}int query(int begin, int end, int k){int l = dat[k].l;int r = dat[k].r;if (l == begin && r == end)return dat[k].d;else if (k >= N - 1)return end - begin;else{int lc = k * 2 + 1;int rc = k * 2 + 2;int mid = dat[lc].r;if (mid >= end)return query(begin, end, lc);else if (begin >= mid)return query(begin, end, rc);elsereturn max(query(begin, mid, lc), query(mid, end, rc));}}}int main(){while (scanf("%d", &n), n){scanf("%d", &q);V.clear();int prev = 1 << 30, temp;for (int i = 0; i < n; i++){scanf("%d", &temp);if (temp != prev)V.push_back(i);prev = temp;}init();build(0);while (q--){scanf("%d %d", &a, &b);printf("%d\n", query(a - 1, b, 0));}}return 0;}

把TLE的平方分割法也贴下吧。。毕竟写了好久。。

#include<cstdio>#include<cmath>#include<vector>#include<map>using namespace std;namespace{int n, q, a, b, dat[100000], B;struct Bucket{int left, right, maxx;};vector<Bucket*> V;Bucket *count(int begin, int end){Bucket *p = new Bucket();map<int, int> M;int maxx = 0;for (int i = begin; i < end; i++){if (M.find(dat[i]) == M.end())M[dat[i]] = 1;elseM[dat[i]]++;maxx = max(M[dat[i]], maxx);}p->left = M.begin()->second;p->right = (--M.end())->second;p->maxx = maxx;return p;}void init(){B = (int) sqrt(n * 1.0);int begin = 0, end;while (begin < n){end = min(n, begin + B);V.push_back(count(begin, end));begin += B;}}void destory(){for (size_t i = 0; i < V.size(); i++)delete V[i];V.clear();}void solve(){a--;int begin = a;int end = min((a / B + 1) * B, b);Bucket *p = count(begin, end);int maxx = p->maxx, right = p->right;while (end < b){begin = end;if (begin + B <= b)p = V[end / B];elsep = count(end, b);end = min(begin + B, b);if (dat[begin] == dat[end - 1]){if (dat[begin - 1] == dat[begin]){right += p->right;maxx = max(right, maxx);}else{right = p->right;maxx = max(right, maxx);}}else{if (dat[begin - 1] == dat[begin])maxx = max(right + p->left, maxx);maxx = max(p->maxx, maxx);right = p->right;}}printf("%d\n", maxx);}}int main(){//freopen("input/3368.in", "r", stdin);//freopen("output/3368.ot", "w", stdout);while (scanf("%d", &n), n){scanf("%d", &q);for (int i = 0; i < n; i++)scanf("%d", &dat[i]);init();while (q--){scanf("%d %d", &a, &b);solve();}destory();}return 0;}


0 0