loj #6468. 魔法
题目大意还是比较清楚的吧
先考虑
l
=
1
,
r
=
n
l = 1, r = n
l=1,r=n怎么做
可以考虑每个魔法球对每个位置的贡献
假设当前位置为
a
a
a,下一个和它种类相同的魔法球位置为
b
b
b
设
m
i
d
=
a
+
b
2
mid = \frac{a+b}{2}
mid=2a+b
那么对于
[
a
,
m
i
d
]
[a,mid]
[a,mid]这个区间都用
a
a
a来贡献(选a),
[
m
i
d
+
1
,
b
]
[mid + 1, b]
[mid+1,b]用
b
b
b来贡献
因为求的是
∣
p
−
p
o
s
∣
|p - pos|
∣p−pos∣
就分两种情况,p > pos 和 p <= pos
然后可以用几个树状数组维护一下
考虑100分怎么做
先把对于颜色
[
l
,
r
]
[l,r]
[l,r]可以拆分成
[
1
,
r
]
−
[
1
,
l
−
1
]
[1, r] - [1, l - 1]
[1,r]−[1,l−1],然后把每个询问拆分成两个前缀和,再按照颜色从小到大排序
然后每次就把一种颜色插入序列中,再算对每个询问的贡献就好了
具体看代码吧
code:
#include<bits/stdc++.h>
#define int long long
#define N 2000005
#define lowbit(x) (x & -x)
using namespace std;
struct BIT{
int tree[N];
void update(int x, int y){
for(;x < N; x += lowbit(x)) tree[x] += y;
}
int query(int x){
int ret = 0;
for(; x; x -= lowbit(x)) ret += tree[x];
return ret;
}
void add(int l, int r, int x){
if(l > r) return;
update(l, x), update(r + 1, - x);
}
}L, R, Ls, Rs;//L 表示贡献点在当前点的左边, Ls 表示有几个贡献点 R,Rs同理
struct A{
int pos, col, id, o;
}q[N];
int cmp(A x, A y){
return x.col < y.col;
}
int n, Q, m, ANS[N];
vector<int> a[N];
signed main(){
scanf("%lld%lld", &n, &Q);
for(int i = 1; i <= n; i ++){
int x;
scanf("%lld", &x);
a[x].push_back(i);//把每个颜色出现的位置记录下来,方便插入颜色
}
for(int i = 1; i <= Q; i ++){
int p, l, r;
scanf("%lld%lld%lld", &p, &l, &r);
q[++ m].pos = p, q[m].col = l - 1, q[m].id = i, q[m].o = - 1;
q[++ m].pos = p, q[m].col = r, q[m].id = i, q[m].o = 1;//拆分成前缀和的形式
}
sort(q + 1, q + 1 + m, cmp);
int pos = 0;
for(int col = 1; col <= n; col ++){
int mm = a[col].size();
if(mm){//如果有颜色就插入
R.add(1, a[col][0], a[col][0]), Rs.add(1, a[col][0], 1);//考虑第一个以前的
for(int j = 0; j < mm - 1; j ++){//中间的
int mid = (a[col][j] + a[col][j + 1]) / 2;
L.add(a[col][j] + 1, mid, a[col][j]), Ls.add(a[col][j] + 1, mid, 1);
R.add(mid + 1, a[col][j + 1], a[col][j + 1]), Rs.add(mid + 1, a[col][j + 1], 1);
}
L.add(a[col][mm - 1] + 1, n, a[col][mm - 1]), Ls.add(a[col][mm - 1] + 1, n, 1);//最后一个往后的
}
while(pos + 1 <= m && q[pos + 1].col <= col){
pos ++;
int p = q[pos].pos;
if(q[pos].col == col) ANS[q[pos].id] += q[pos].o * (R.query(p) - Rs.query(p) * p), ANS[q[pos].id] += q[pos].o * (Ls.query(p) * p - L.query(p));//计算贡献
}
}
for(int i = 1; i <= Q; i ++) printf("%lld\n", ANS[i]);
return 0;
}
离线大法吼哇