标签:
题面戳这儿-> 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();
}
}
?
标签:
原文地址:http://www.cnblogs.com/AwD-/p/5350000.html