2017.11.06 T2
好气,我这道题写的权值线段树,结果维护的时候搞忘清零了,只有 20 分,加上清零就 A了,当然我是指的评测机上AC,在 OJ 上要 T 一些点,有点小气。
我用权值线段树,在修改的时候加了一个 log2H , 但我的询问是 log2H 的,比较已经过了的代码修改是 O(H) 询问也是 O(H) ,我的算法还是被卡了。
权值线段树
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read() {
int i = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1; ch = getchar();
}
while(isdigit(ch)) {
i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
}
return i * f;
}
const int MAXH = 1e4 + 5;
int h[MAXH], tr[MAXH << 2], MAX, mx;
inline void update(int k) {
tr[k] = tr[k << 1] + tr[k << 1 | 1];
}
inline void build(register int k, register int s, register int t) {
if(s == t) return (void)(tr[k] = h[s]);
int mid = s + t >> 1;
build(k << 1, s, mid);
build(k << 1 | 1, mid + 1, t);
update(k);
}
inline int query(register int k, register int s, register int t, register int x) {
if(s == t) return s;
int mid = s + t >> 1;
if(tr[k << 1 | 1] >= x) return query(k << 1 | 1, mid + 1, t, x);
else return query(k << 1, s, mid, x - tr[k << 1 | 1]);
}
inline int querysze(register int k, register int s, register int t, register int l, register int r) {
if(l <= s && t <= r) return tr[k];
int mid = s + t >> 1, res = 0;
if(l <= mid) res = querysze(k << 1, s, mid, l, r);
if(mid < r) res += querysze(k << 1 | 1, mid + 1, t, l, r);
return res;
}
inline void modify(register int k, register int s, register int t, register int pos, register int x) {
if(s == t) return (void)(tr[k] += x);
int mid = s + t >> 1;
if(pos <= mid) modify(k << 1, s, mid, pos, x);
else modify(k << 1 | 1, mid + 1, t, pos, x);
update(k);
}
int main() {
int n = read(), m = read();
for(register int i = 1; i <= n; ++i) {
int x = read();
++h[x + 1], mx = max(mx, x + 1);
}
int MAX = 1e4 + 2;
build(1, 1, MAX);
int flag = 0;
for(register int i = 1; i <= m; ++i) {
int x = read();
int now = query(1, 1, MAX, x);
if(now == 1) {
flag = 1;
cout<1;
return 0;
}
int sze = querysze(1, 1, MAX, now, mx);
if(now == mx) {
int delta = sze - x;
if(delta)
modify(1, 1, MAX, now, -x),
modify(1, 1, MAX, now - 1, x),
h[now - 1] += x, h[now] -= x;
else
modify(1, 1, MAX, now, -sze),
modify(1, 1, MAX, now - 1, sze),
h[now - 1] += sze, h[now] -= sze, --mx;
}
else {
int delta = sze - x;
int nowsze = h[now];
modify(1, 1, MAX, now, -nowsze + delta),
modify(1, 1, MAX, now - 1, nowsze - delta),
h[now - 1] += nowsze - delta, h[now] = delta;
for(register int i = mx; i >= now + 1; --i) {
if(h[i])
modify(1, 1, MAX, i, -h[i]),
modify(1, 1, MAX, i - 1, h[i]);
}
for(int i = now + 1; i <= mx; ++i)
if(h[i]) h[i - 1] += h[i], h[i] = 0;
--mx;
}
}
if(!flag) cout<
普通的数组,但是AC
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
inline int read() {
int i = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = -1; ch = getchar();
}
while(isdigit(ch)) {
i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
}
return i * f;
}
const int MAXH = 1e4 + 5;
int h[MAXH], tr[MAXH << 2], MAX, mx;
inline int find(int x) {
int now = 0;
for(int i = mx; i >= 1; --i) {
now += h[i];
if(now >= x) return i;
}
}
inline int query(int x) {
int now = 0;
for(int i = mx; i >= x; --i)
now += h[i];
return now;
}
int main() {
int n = read(), m = read();
for(register int i = 1; i <= n; ++i) {
int x = read();
++h[x + 1], mx = max(mx, x + 1);
}
int MAX = mx;
int flag = 0;
for(register int i = 1; i <= m; ++i) {
int x = read();
int now = find(x);
if(now == 1) {
flag = 1;
cout<1;
return 0;
}
int sze = query(now);
if(now == mx) {
int delta = sze - x;
if(delta) h[now - 1] += x, h[now] -= x;
else h[now - 1] += sze, h[now] -= sze, --mx;
}
else {
int delta = sze - x;
int nowsze = h[now];
h[now - 1] += nowsze - delta, h[now] = delta;
for(int i = now + 1; i <= mx; ++i)
h[i - 1] += h[i], h[i] = 0;
--mx;
}
}
if(!flag) cout<