题面戳这儿-> 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();
}
}
?