1.无旋treap写法:
以下代码会在第六个点TLE,估计是常数比较大!
#pragma GCC optimize("Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
template<class T>void read(T& x)
{
x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
x*=f;
}//快读
template<class T>void write(T& x)
{
int num=0;char c[40];
while(x)c[++num]=(x%10)+48,x/=10;
while(num)putchar(c[num--]);
}//快写
const int N=2e6+10;
const int INF=1e9+10;
mt19937 rnd(time(0));
struct Node
{
int l, r,size;
int key, pos,mn;
unsigned int val;
}tr[N];
int root, tot, rt1, rt2, rt3;
int New(int key, int pos)
{
int id = ++tot;
tr[id].l=tr[id].r=0;
tr[id].size = 1;
tr[id].key = key;
tr[id].pos = tr[id].mn = pos;
tr[id].val = rnd();
return id;
}
void pushup(int p)
{
tr[p].size = tr[tr[p].l].size + tr[tr[p].r].size + 1;
tr[p].mn = min(tr[p].pos, min(tr[tr[p].l].mn, tr[tr[p].r].mn));
}
void split(int now,int k,int &x,int &y)
{
if (!now)x = y = 0;
else {
if (tr[now].key <= k)
x = now, split(tr[now].r, k, tr[now].r, y);
else y = now, split(tr[now].l, k, x, tr[now].l);
pushup(now);
}
}
int merge(int x, int y)
{
if (!x || !y)return x + y;
if (tr[x].val > tr[y].val)
{
tr[x].r = merge(tr[x].r, y);
pushup(x);
return x;
}
else
{
tr[y].l = merge(x, tr[y].l);
pushup(y);
return y;
}
}
void insert(int x, int pos)
{
split(root, x, rt1, rt2);
rt1 = merge(rt1 , New(x , pos));
root = merge(rt1, rt2);
}
pair<int,int> erase(int &now,int mn)
{
pair<int, int>ans;
if (tr[now].pos == mn)
{
ans = { tr[now].key,tr[now].pos };
now = merge(tr[now].l, tr[now].r);
return ans;
}
if (tr[tr[now].l].mn == mn)ans = erase(tr[now].l, mn);
else ans = erase(tr[now].r, mn);
pushup(now);
return ans;
}
pair<int, int> erase(int& now)
{
pair<int, int>ans;
if (!tr[now].l)
{
ans = { tr[now].key,tr[now].pos };
now = merge(tr[now].l, tr[now].r);
return ans;
}
ans = erase(tr[now].l);
pushup(now);
return ans;
}
int a[N];
void solve()
{
int n, c;
read(n), read(c);
tr[0] = { 0,0,0,0,INF,INF,rnd() };
for (int i = 1;i <= n;++i)tr[i] = { 0,0,0,0,0,0,0 };
root = tot = 0;
int ans = 0;
for (int i = 1;i <= n;++i)
{
read(a[i]);
split(root, a[i] - 1, rt1, rt2);
if (!rt2)
{
root = merge(rt1, rt2);
++ans;
int r = c - a[i];
insert(r, ans);
}
else {
pair<int, int>now = erase(rt2, tr[rt2].mn);
root = merge(rt1, rt2);
insert(now.first - a[i], now.second);
}
}
write(ans);putchar(' ');
for (int i = 1;i <= n;++i)tr[i] = { 0,0,0,0,0,0,0 };
root = tot = 0;
ans = 0;
for (int i = 1;i <= n;++i)
{
split(root, a[i] - 1, rt1, rt2);
if (!rt2)
{
root = merge(rt1, rt2);
++ans;
int r = c - a[i];
insert(r, ans);
}
else
{
pair<int, int>now = erase(rt2);
root = merge(rt1, rt2);
insert(now.first - a[i], now.second);
}
}
write(ans);putchar('\n');
}
int main()
{
int T;
read(T);
while (T--) {
solve();
}
return 0;
}
2.将第二部分换成map后在第八个点TLE,无旋treap常数这么大吗,有点出乎意料······
#pragma GCC optimize("Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
template<class T>void read(T& x)
{
x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
x*=f;
}//快读
template<class T>void write(T& x)
{
int num=0;char c[40];
while(x)c[++num]=(x%10)+48,x/=10;
while(num)putchar(c[num--]);
}//快写
const int N=2e6+10;
const int INF=1e9+10;
mt19937 rnd(time(0));
struct Node
{
int l, r,size;
int key, pos,mn;
unsigned int val;
}tr[N];
int root, tot, rt1, rt2, rt3;
int New(int key, int pos)
{
int id = ++tot;
tr[id].l=tr[id].r=0;
tr[id].size = 1;
tr[id].key = key;
tr[id].pos = tr[id].mn = pos;
tr[id].val = rnd();
return id;
}
void pushup(int p)
{
tr[p].size = tr[tr[p].l].size + tr[tr[p].r].size + 1;
tr[p].mn = min(tr[p].pos, min(tr[tr[p].l].mn, tr[tr[p].r].mn));
}
void split(int now,int k,int &x,int &y)
{
if (!now)x = y = 0;
else {
if (tr[now].key <= k)
x = now, split(tr[now].r, k, tr[now].r, y);
else y = now, split(tr[now].l, k, x, tr[now].l);
pushup(now);
}
}
int merge(int x, int y)
{
if (!x || !y)return x + y;
if (tr[x].val > tr[y].val)
{
tr[x].r = merge(tr[x].r, y);
pushup(x);
return x;
}
else
{
tr[y].l = merge(x, tr[y].l);
pushup(y);
return y;
}
}
void insert(int x, int pos)
{
split(root, x, rt1, rt2);
rt1 = merge(rt1 , New(x , pos));
root = merge(rt1, rt2);
}
pair<int,int> erase(int &now,int mn)
{
pair<int, int>ans;
if (tr[now].pos == mn)
{
ans = { tr[now].key,tr[now].pos };
now = merge(tr[now].l, tr[now].r);
return ans;
}
if (tr[tr[now].l].mn == mn)ans = erase(tr[now].l, mn);
else ans = erase(tr[now].r, mn);
pushup(now);
return ans;
}
pair<int, int> erase(int& now)
{
pair<int, int>ans;
if (!tr[now].l)
{
ans = { tr[now].key,tr[now].pos };
now = merge(tr[now].l, tr[now].r);
return ans;
}
ans = erase(tr[now].l);
pushup(now);
return ans;
}
int a[N];
void solve()
{
int n, c;
read(n), read(c);
tr[0] = { 0,0,0,0,INF,INF,rnd() };
for (int i = 1;i <= n;++i)tr[i] = { 0,0,0,0,0,0,0 };
root = tot = 0;
int ans = 0;
for (int i = 1;i <= n;++i)
{
read(a[i]);
split(root, a[i] - 1, rt1, rt2);
if (!rt2)
{
root = merge(rt1, rt2);
++ans;
int r = c - a[i];
insert(r, ans);
}
else {
pair<int, int>now = erase(rt2, tr[rt2].mn);
root = merge(rt1, rt2);
insert(now.first - a[i], now.second);
}
}
write(ans);putchar(' ');
ans = 0;
map<int, int>mp;
for (int i = 1;i <= n;++i)
{
auto it = mp.lower_bound(a[i]);
if (it == mp.end())++mp[c - a[i]], ++ans;
else{
int r = it->first - a[i];
--(it->second);
if (it->second == 0)mp.erase(it);
++mp[r];
}
}
write(ans);putchar('\n');
}
int main()
{
int T;
read(T);
while (T--) {
solve();
}
return 0;
}
3.再将第一部分换成线段树,成功AC。
#pragma GCC optimize("Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
template<class T>void read(T& x)
{
x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
x*=f;
}//快读
template<class T>void write(T& x)
{
int num=0;char c[40];
while(x)c[++num]=(x%10)+48,x/=10;
while(num)putchar(c[num--]);
}//快写
const int N = 5e6 + 10;
const int INF = 1e9;
int n, c;
int a[N];
int tr[N], ans;
#define ls p<<1
#define rs p<<1|1
void pushup(int p)
{
tr[p] = max(tr[ls], tr[rs]);
}
void update(int p, int pl, int pr, int val)
{
if (pl == pr)
{
if (tr[p] == c)++ans;
tr[p] -= val;
return;
}
int mid = pl + pr >> 1;
if (tr[ls] >= val)update(ls, pl, mid, val);
else update(rs, mid + 1, pr, val);
pushup(p);
}
void solve()
{
read(n), read(c);
for (int i = 1;i <= 4 * n;++i)tr[i] = c;
ans = 0;
for (int i = 1;i <= n;++i)
{
read(a[i]);
update(1, 1, n, a[i]);
}
write(ans);putchar(' ');
ans = 0;
map<int, int>mp;
for (int i = 1;i <= n;++i)
{
auto it = mp.lower_bound(a[i]);
if (it == mp.end())++mp[c - a[i]], ++ans;
else{
int r = it->first - a[i];
--(it->second);
if (it->second == 0)mp.erase(it);
++mp[r];
}
}
write(ans);putchar('\n');
}
int main()
{
int T;
read(T);
while (T--) {
solve();
}
return 0;
}
总结:以后1e6的数据再也不敲平衡树了!!!