这题网上有题解,贴这题主要是记录自己以前写的SBT,觉得maintain 和左右旋写得比较好,可能板子比我写得好.不过没看过.
ch[x][2]代表sbt的两个孩子.
今天突然发现前面写的平衡树有点错误.
#include
#include
#include
#include
#pragma warning(disable:4996)
using namespace std;
int n;
const int bign = 100033;
int s[bign];
int m[bign];
int r[bign];
int q;
int nid;
int msize[6*bign];
int num[6*bign];
int ch[6*bign][2];
int tseq[bign];
int ep[bign];
int sp[bign];
int te[bign];
int ts[bign];
int mroot;
long long int sumT;
long long int tsumT[6*bign];
int vst[bign];
set mset1;
set mset2;
bool cmpts(int x1, int y1)
{
if (sp[x1] < sp[y1] || (sp[x1] == sp[y1] && x1 < y1))
return true;
return false;
}
bool cmpte(int x1, int y1)
{
if (ep[x1] < ep[y1] || (ep[x1] == ep[y1] && x1 < y1))
return true;
return false;
}
inline void pushup(int &x)
{
msize[x] = msize[ch[x][0]] + msize[ch[x][1]] + 1;
tsumT[x] = tsumT[ch[x][0]] + tsumT[ch[x][1]] + num[x];
}
inline void rotate(int &x, int flag)//flag = 1 rotate with rightchild
{
int nroot = ch[x][flag];
ch[x][flag] = ch[nroot][!flag];
ch[nroot][!flag] = x;
pushup(x);
pushup(nroot);
x = nroot;
}
void maintain(int &x, int flag)
{
int &m2 = ch[x][flag];
int &m1 = ch[x][!flag];
if (msize[ch[m2][!flag]] > msize[m1])
{
rotate(m2, !flag);
rotate(x, flag);
}
else if (msize[ch[m2][flag]] > msize[m1])
{
rotate(x, flag);
}
else
{
return;
}
maintain(ch[x][0], 0);
maintain(ch[x][1], 1);
maintain(x, 1);
maintain(x, 0);
}
inline int Query(const int &mroot, int x)
{
int troot = mroot;
int ret = 0;
sumT = 0;
while (troot)
{
if (x >= num[troot])
{
ret += (1 + msize[ch[troot][0]]);
sumT += tsumT[ch[troot][0]] + num[troot];
troot = ch[troot][1];
}
else
{
troot = ch[troot][0];
}
}
return ret;
}
void minsert(int &nowroot, int x)
{
if (nowroot == 0)
{
nid++;
msize[nid] = 1;
num[nid] = x;
tsumT[nid] = x;
nowroot = nid;
return;
}
msize[nowroot]++;
tsumT[nowroot] += x;
if (num[nowroot] < x)
{
minsert(ch[nowroot][1], x);
}
else
{
minsert(ch[nowroot][0], x);
}
//pushup(nowroot);
maintain(nowroot, (x > num[nowroot]));
}
int mdelete(int &nowroot, int x)
{
//msize[nowroot]--;
int ret = 0;
if (x == num[nowroot] || (x > num[nowroot] && !ch[nowroot][1]) || (x < num[nowroot] && !ch[nowroot][0]))
{
if (!ch[nowroot][0])
{
ret = num[nowroot];
nowroot = ch[nowroot][1];
return ret;
}
else if (!ch[nowroot][1])
{
ret = num[nowroot];
nowroot = ch[nowroot][0];
return ret;
}
else
{
num[nowroot] = mdelete(ch[nowroot][0], x + 1);
pushup(nowroot);
return num[nowroot];
}
}
else
{
if (x > num[nowroot])
{
int tmp = mdelete(ch[nowroot][1], x);
pushup(nowroot);
return tmp;
}
else
{
int tmp = mdelete(ch[nowroot][0], x);
pushup(nowroot);
return tmp;
}
}
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%d%d%d", s + i, m + i, r + i);
}
scanf("%d", &q);
for (int i = 1; i <= q; i++)
{
//int t, ts, te;
ts[i] = i;
te[i] = i;
scanf("%d%d%d", &tseq[i], &sp[i], &ep[i]);
}
sort(ts + 1, ts + q + 1, cmpts);
sort(te + 1, te + q + 1, cmpte);
int nowl = 1;
int nowr = 1;
mroot = 0;
long long int ans = 0;
memset(vst, -1, sizeof(vst));
for (int i = 1;i <= n; i++)
{
while (sp[ts[nowl]] <= i && nowl <= q)
{
int t1 = ts[nowl];
set::iterator lb1 = mset1.upper_bound(t1);
int tcnt = 0;
int tsum = 0;
if (lb1 != mset1.end())
{
tcnt++;
tsum += tseq[*lb1] - tseq[t1];
minsert(mroot, tseq[*lb1] - tseq[t1]);
}
lb1 = mset2.upper_bound(-t1);
if (lb1 != mset2.end())
{
tcnt++;
tsum += tseq[t1] - tseq[-*lb1];
minsert(mroot, tseq[t1] - tseq[-*lb1]);
}
if (tcnt == 2)
{
mdelete(mroot, tsum);
}
mset1.insert(t1);
mset2.insert(-t1);
nowl++;
}
if (mset1.size() > 0)
vst[i] = *mset1.begin();
if (msize[mroot] > 0)
{
if (r[i] > 0)
{
int x = Query(mroot, m[i] / r[i]);
ans += 1ll * sumT * r[i] + 1ll * m[i] * (msize[mroot] - x);
}
}
while (ep[te[nowr]] <= i && nowr <= q)
{
int t2 = te[nowr];
int tcnt = 0;
int tsum = 0;
set::iterator lb1 = mset1.upper_bound(t2);
if (lb1 != mset1.end())
{
tcnt++;
tsum += tseq[*lb1] - tseq[t2];
mdelete(mroot, tseq[*lb1] - tseq[t2]);
}
lb1 = mset2.upper_bound(-t2);
if (lb1 != mset2.end())
{
tcnt++;
tsum += tseq[t2] - tseq[-*lb1];
mdelete(mroot, tseq[t2] - tseq[-*lb1]);
}
if (tcnt == 2)
minsert(mroot, tsum);
mset1.erase(t2);
mset2.erase(-t2);
nowr++;
}
// printf("%lld\n", ans);
}
for (int i = 1; i <= n; i++)
{
if (vst[i] >= 0)
{
ans += (s[i] + 1ll * tseq[vst[i]] * r[i] < m[i]) ? (s[i] + 1ll * tseq[vst[i]] * r[i]) : m[i];
}
}
printf("%lld\n", ans);
}
/*
12
0 10 1
0 12 1
0 20 1
0 12 1
0 10 1
0 10 1
0 10 1
0 10 1
0 10 1
0 10 1
0 10 1
0 10 1
2 100 10
7
5 1 5
6 1 5
7 1 5
20 1 5
40 5 10
100 2 3
1000 1 12
*/