免責事項:この記事はブロガーオリジナル記事です、続くBY-SAのCC 4.0を著作権契約、複製、元のソースのリンクと、この文を添付してください。
タイトル
データを、各データ・インデックス= 3%と5のクエリー数列値を追加および削除することができ、列の多数の小さなを維持
問題の解決策
常にそれが唯一のその種の良い見つけるのに長い時間のように、一種のではないと思った最初は、少し簡単なポイント
の個別操作は、STLのLOWER_BOUND二つの機能とユニークで簡単に比較的簡単に行うことができている
理由は、オフラインセグメントからですノード操作の削除や追加を完了することができませんでしツリーの限界、最初からツリーラインのサイズが固定されるので、そのオフラインの方法を使用して、我々はすべてのデータの総数でツリーラインを確立するために、データの量を知ることができるようになります、これは、私たちは、その後、0に減少し、リーフ・ノードの下にCNT-1で運転削除、ノードの子の数を記録するために、削除操作のCNTを使用するので、このことができ、ツリーラインを高めるために、変形「追加」操作を完了しますノードがまだそこに実際にあるが、値が0であるため、私たちのフォロー和の計算には影響しません、CNTとターゲットの列の下に多数の彼の影響力を排除するために、この変数
のセグメントツリーは、その後、何も難しくありません、シングルポイントの更新セグメントツリーです、左のサブツリー右部分木プラス指数に必要右側のサブツリーの削減という、例えば、右のために注意すべきです 合計欄のツリーの最初の位置は(1 +はsizeof(左部分木))である必要があり、この時間は、CNTの変数がで重要な役割を果たしています
コード
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define maxn 100010
#define lson rt<<1
#define rson rt<<1|1
#define ll long long int
using namespace std;
int a[maxn],b[maxn],T;
char p[maxn],c[5];
struct Tre
{
int l,r,cnt;
ll sum[5];
}tre[maxn<<2];
void pushup(int rt)
{
for(int i=0;i<5;i++)
tre[rt].sum[i]=tre[lson].sum[i]+tre[rson].sum[((i-tre[lson].cnt)%5+5)%5];
}
void build(int rt,int l,int r)
{
tre[rt].l=l;
tre[rt].r=r;
tre[rt].cnt=0;
for(int i=0;i<5;i++) tre[rt].sum[i]=0;
if(l==r) return;
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
}
void update(int rt,int pos,int add)
{
tre[rt].cnt+=add;
if(tre[rt].l==tre[rt].r){
tre[rt].sum[1]+=add*b[pos-1];
return ;
}
int mid=(tre[rt].l+tre[rt].r)>>1;
if(pos<=mid) update(lson,pos,add);
else update(rson,pos,add);
pushup(rt);
}
int main()
{
//freopen("1.txt","r",stdin);
int k,j;
while(scanf("%d",&T)==1){
k=0;j=0;
int f;
for(int i=1;i<=T;i++){
scanf("%s",c);
p[i]=c[0];
if(p[i]!='s'){
scanf("%d",&a[k++]);
b[k-1]=a[k-1];
}
}
sort(b,b+k);
int n=unique(b,b+k)-b;
build(1,1,n);
for(int i=1;i<=T;i++){
if(p[i]=='s'){
printf("%I64d\n",tre[1].sum[3]);
continue;
}
if(p[i]=='a') f=1;
else f=-1;
int pos=lower_bound(b,b+n,a[j++])-b+1;
update(1,pos,f);
}
}
//fclose(stdin);
}