码迷,mamicode.com
首页 > 其他好文 > 详细

3337: ORZJRY I

时间:2016-04-03 17:28:26      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:

题面戳这儿-> http://www.lydsy.com/JudgeOnline/problem.php?id=3337

历时三天终于AC……

? ? ? ?

首先先膜发吉利 orz。

明显这是一道数据结构题

由于没有任何树能支持这么多操作(至少我不会),因此这明显这是一道块状链表模板题,对每个块排个序就好。

主要是块状链表需要注意一点:在询问打了标记的块时千万不要向下推送标记,不然你会T的。

细节很多,非常多——我到现在还是没有掌握二分的正确姿势。

搞对拍时数据生成器和暴力都写错了,果然我还是太young

大致就是这样

以下是代码:

#include <iostream>

#include <algorithm>

#include <cstdio>

#include <cmath>

#include <queue>

#include <deque>

#include <cstring>

#define INF (int)1e10

#define eps 1e-7

#define pi acos(-1)

//#define __advance __attribute__((optimize("O2")))

typedef long long LL;

using namespace std;

template <class T> inline

void read(T &num)

{

bool start = 0, neg = 0;

char c; num = 0;

while ((c = getchar()) != EOF)

{

if (c == ‘-‘) start = neg = 1;

else if (c >= ‘0‘ && c <= ‘9‘)

{

start = 1;

(num *= 10) += c - ‘0‘;

}

else if (start) break;

}

if (neg) num = -num;

}

//Hello world!

#define N 1100000

typedef vector <int> ::iterator VE;

struct node

{

vector <int> d, s;

node *nt;

int tag_re, tag_sa, tag_ad;

LL sum;

}map[N], *bg;

int bound;

int n, q;

queue <node*> vv;

void push_down(node &p)

{

if (p.tag_re) p.tag_re = 0, reverse(p.d.begin(), p.d.end());

if (p.tag_sa) {for (int i = 0; i < p.d.size(); ++ i) p.d[i] = p.tag_sa; p.tag_sa = 0; }

if (p.tag_ad) {for (int i = 0; i < p.d.size(); ++ i) p.d[i] += p.tag_ad; p.tag_ad = 0;}

}

void updatenode(node &p)

{

p.sum = 0; for (int i = 0; i < p.d.size(); ++ i) p.sum += p.d[i];

p.s.assign(p.d.begin(), p.d.end());

sort(p.s.begin(), p.s.end());

}

void print()

{

cout << "print:";

for (node *p = bg; p != NULL; p = p->nt)

{

cout << "| ";

if (p->tag_re) cout << "R ";

if (p->tag_sa) cout << "S " << p->tag_sa << ": ";

if (p->tag_ad) cout << "A " << p->tag_ad << ": ";

for (VE i = p->d.begin(); i != p->d.end(); ++ i)

if (p->tag_sa) cout << p->tag_sa + p->tag_ad << " ";

else cout << *i + p->tag_ad << " ";

}

cout << "\n";

}

void clear(node &p)

{

p.nt = NULL; p.tag_re = p.tag_sa = p.tag_ad = p.sum = 0;

p.d.clear(); p.s.clear();

}

void dele(node &p)

{

vv.push(&p); clear(p);

}

node *new__()

{

node *p = vv.front(); vv.pop(); return p;

}

void merge(node &p)

{

node *q = p.nt;

push_down(p); push_down(*q);

p.d.insert(p.d.end(), q->d.begin(), q->d.end());

p.nt = q->nt; dele(*q);

updatenode(p);

}

void spilt(node &p, VE pos)

{

push_down(p);

node *q = new__();

q->d.assign(pos, p.d.end()); p.d.erase(pos, p.d.end());

q->nt = p.nt; p.nt = q;

updatenode(p); updatenode(*q);

}

void updateall()

{

bound = sqrt(n);

for (node *p = bg; p != NULL; p = p->nt)

{

while ((p->nt != NULL) && (p->d.size() + p->nt->d.size() <= bound))

merge(*p);

}

}

void find(int num, node **p, VE &pos)

{

int q = 0; *p = bg;

for (; q + (*p)->d.size() <= num; q += (*p)->d.size(), *p = (*p)->nt);

pos = (*p)->d.begin();

for (; q + 1 <= num; ++ q, ++ pos);

}

void do_insert(int num, int val)

{

node *p; VE pos;

find(num + 1, &p, pos);

push_down(*p);

p->d.insert(pos, val);

updatenode(*p);

}

void do_erase(int num)

{

node *p; VE pos;

find(num, &p, pos);

push_down(*p);

p->d.erase(pos);

updatenode(*p);

}

void get_inter(int l, int r, node **lp, node **rp)

{

VE pos;

find(l, lp, pos); spilt(**lp, pos);

find(r + 1, rp, pos); spilt(**rp, pos);

find(r, rp, pos);

}

void do_reverse(int l, int r)

{

node *lp, *rp; get_inter(l, r, &lp, &rp);

for (node *p = lp->nt, *q = rp->nt, *np; ; q = p, p = np)

{

p->tag_re ^= 1;

np = p->nt;

p->nt = q;

if (p == rp) break;

}

lp->nt = rp;

}

void do_move(int l, int r, int k)

{

node *lp, *mp, *rp, *np;

get_inter(l, r - k, &lp, &mp);

get_inter(r - k + 1, r, &mp, &rp);

np = lp->nt;

lp->nt = mp->nt;

mp->nt = rp->nt;

rp->nt = np;

}

void do_add(int l, int r, int val)

{

node *lp, *rp; get_inter(l, r, &lp, &rp);

for (node *p = lp->nt; p != rp->nt; p = p->nt)

{

p->tag_ad += val;

p->sum += p->d.size() * val;

}

}

void do_same(int l, int r, int val)

{

node *lp, *rp; get_inter(l, r, &lp, &rp);

for (node *p = lp->nt; p != rp->nt; p = p->nt)

{

p->tag_ad = 0;

p->tag_sa = val;

p->sum = p->d.size() * val;

}

}

LL ask_sum(int l, int r)

{

node *lp, *rp; get_inter(l, r, &lp, &rp);

LL ansp = 0;

for (node *p = lp->nt; p != rp->nt; p = p->nt)

{

ansp += p->sum;

}

return ansp;

}

int ask_range(int l, int r)

{

node *lp, *rp; get_inter(l, r, &lp, &rp);

int maxp = -INF, minp = INF;

for (node *p = lp->nt; p != rp->nt; p = p->nt)

if (p->d.size() == 0);

else if (p->tag_sa)

{

minp = min(minp, p->tag_sa + p->tag_ad);

maxp = max(maxp, p->tag_sa + p->tag_ad);

}

else

{

minp = min(minp, p->s[0] + p->tag_ad);

maxp = max(maxp, p->s[p->d.size() - 1] + p->tag_ad);

}

return maxp - minp;

}

int ask_near(int l, int r, int val)

{

node *lp, *rp; get_inter(l, r, &lp, &rp);

int ansp = INF;

for (node *p = lp->nt; p != rp->nt; p = p->nt)

if (p->tag_sa)

{

ansp = min(ansp, abs(val - p->tag_sa - p->tag_ad));

}

else

{

VE id = lower_bound(p->s.begin(), p->s.end(), val - p->tag_ad);

if (id != p->s.end()) ansp = min(ansp, *id - val + p->tag_ad);

if (id != p->s.begin())

id --,

ansp = min(ansp, val - *id - p->tag_ad);

}

return ansp;

}

int ask_sa(int l, int r, int k)

{

node *lp, *rp; get_inter(l, r, &lp, &rp);

int ansp = 0;

int ll = 0, rr = INF;

while (ll < rr)

{

int mm = (ll + rr) / 2 + 1;

ansp = 1;

for (node *p = lp->nt; p != rp->nt; p = p->nt)

if (p->tag_sa)

{

if (p->tag_sa + p->tag_ad < mm) ansp += p->d.size();

}

else

{

VE id = upper_bound(p->s.begin(), p->s.end(), mm - p->tag_ad - 1);

ansp += id - p->s.begin();

}

if (k >= ansp) ll = mm; else rr = mm - 1;

}

return ll;

}

int ask_smaller(int l, int r, int val)

{

node *lp, *rp; get_inter(l, r, &lp, &rp);

int ansp = 0;

for (node *p = lp->nt; p != rp->nt; p = p->nt)

if (p->tag_sa)

{

if (p->tag_sa + p->tag_ad < val) ansp += p->d.size();

}

else

{

VE id = upper_bound(p->s.begin(), p->s.end(), val - p->tag_ad - 1);

ansp += id - p->s.begin();

}

return ansp;

}

int main()

{

//cout << sizeof(node);

read(n);

for (int i = n + 2; i < N; ++ i) vv.push(map + i);

bg = map + 0;

for (int i = 0; i <= n + 1; ++ i)

{

int a = -233;

if ((i) && (i <= n)) read(a);

if (i != n + 1) map[i].nt = map + i + 1;

map[i].d.push_back(a);

updatenode(map[i]);

}

updateall();

read(q);

for (int i = 1; i <= q; ++ i)

{

//print();

int a, x, y, z;

LL k;

read(a); read(x);

if (a != 2) read(y);

if ((a != 1) && (a != 2) && (a != 3) && (a != 7) && (a != 8)) read(z);

switch (a)

{

case 1: do_insert(x, y); n ++; break;

case 2: do_erase(x); n --; break;

case 3: do_reverse(x, y); break;

case 4: do_move(x, y, z); break;

case 5: do_add(x, y, z); break;

case 6: do_same(x, y, z); break;

case 7: k = ask_sum(x, y); break;

case 8: k = ask_range(x, y); break;

case 9: k = ask_near(x, y, z); break;

case 10: k = ask_sa(x, y, z); break;

case 11: k = ask_smaller(x, y, z); break;

}

if (a >= 7) cout << k << "\n";

updateall();

}

}

?

3337: ORZJRY I

标签:

原文地址:http://www.cnblogs.com/AwD-/p/5350000.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!