Problem - 1354D - Codeforces
我被卡了:
这道题看到multiset我还真写multiset,结果内存超限。
当然能想到想同的数存到一块,所以用了map,结果还超,诶呦:
set肯定比map大滴,这里可能刚超就结束了,事实上可能占用更大。
思路:
本题是得用树状数组或者线段树存出现次数做,而且内存足够多。
我是用的类构造的线段树。
初始一个1e6的数组,构造里有1e6的这个数组和树状数组,比3e6大,粗算一下吧,4e6 * 4字节 = 16e6 ,也就是16MB,也不超28MB。
————
存出现次数,树状数组记录的前缀和,所以可以二分找到第几个数。
代码:
这个类板子就是我的树状数组1
template<class T>
class BIT//Binary Indexed Tree
{
public:
ll n;//a的大小
vector<T>a;//原数组
vector<T>c;//树状数组
ll lowbit(ll a)
{
return a & -a;
}
T getsum(ll i)
{
T sum = 0;
while (i > 0)
{
sum += c[i];
i -= lowbit(i);
}
return sum;
}
void add(ll i, T v)
{
while (i <= n)
{
c[i] += v;
i = i + lowbit(i);
}
}
BIT(vector<T>_a)
{
a = _a;
n = a.size() - 1;
c = vector<T>(n + 1);
//直接把树建好
for (ll i = 1; i <= n; i++)
{
add(i, a[i]);
}
}
};
void solve(int casen)
{
int n, m;
cin >> n >> m;
vector<int>arr(1000002);
BIT<int> demo(arr);
for (int i = 1; i <= n; i++)
{
int tmp;
cin >> tmp;
demo.add(tmp, 1);
}
for (int i = 1; i <= m; i++)
{
int tmp;
cin >> tmp;
if (tmp < 0)
{
tmp = -tmp;
//二分找第tmp个
int l = 1, r = 1000000;
while (l < r)
{
int mid = l + (r - l) / 2;
if (demo.getsum(mid) >= tmp)
r = mid;
else
l = mid + 1;
}
demo.add(l, -1);//有人给tmp减
}
else
{
demo.add(tmp, 1);
}
}
int l = 1, r = 1000000;
if (demo.getsum(1000000) == 0)
{
cout << 0;
return;
}
while (l < r)
{
int mid = l + (r - l) / 2;
if (demo.getsum(mid) > 0)
{
r = mid;
}
else
l = mid + 1;
}
cout << l;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
for (int i = 1; i <= t; i++)
{
solve(i);
}
return 0;
}