題目鏈接
題目可轉化爲值域線段樹的寫法,題目上說讓求所有區間和的值在L到R之間的有多少個,每一個區間值可以由數組的前綴和快速求出來,設sum[i]爲i之前的和,i小於j即求sum[j]-sum[i]在L到R之間的有多少個,可以轉化爲
sum[j]-R<=sum[i]<=sum[j]-L,用sum[i]建一顆值域線段樹每次詢問在sum[j]-R到sum[j]-L之間的值有多少個累加起來就是結果。
/*
值域線段樹區間裏面存的是在這個區間內的數的個數有多少個
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=7e6+10;
const LL inf=10000000000;
LL x[maxn];
struct AC
{
struct zp
{
LL lson,rson,sum;
} tree[maxn];
int cnt;
int newnode()//動態開闢節點
{
tree[cnt].lson=tree[cnt].rson=-1;
tree[cnt].sum=0;
cnt++;
return cnt-1;
}
void init()
{
cnt=0;
}
void update(LL &k,LL l,LL r,LL num)//更新/插入值
{
if(k==-1) k=newnode();//沒有這個值新開節點
tree[k].sum++;//這個值所處的路線上的值都加一
if(l==r) return ;
LL mid=(l+r)>>1;
if(num<=mid)
update(tree[k].lson,l,mid,num);
else
update(tree[k].rson,mid+1,r,num);
}
LL query(LL k,LL l,LL r,LL ql,LL qr)//查詢區間內有多少個值
{
if(k==-1) return 0;
if(l==ql&&r==qr)
return tree[k].sum;
LL mid=(l+r)>>1;
if(qr<=mid)
return query(tree[k].lson,l,mid,ql,qr);
else if(ql>mid)
return query(tree[k].rson,mid+1,r,ql,qr);
else
return query(tree[k].lson,l,mid,ql,mid)+query(tree[k].rson,mid+1,r,mid+1,qr);
}
} ac;
int main()
{
LL n,L,R;
while(~scanf("%lld%lld%lld",&n,&L,&R))
{
ac.init();//注意初始化
scanf("%lld",&x[0]);
for(int i=1; i<n; i++)
scanf("%lld",&x[i]),x[i]+=x[i-1];
LL root=-1;
ac.update(root,-inf,inf,0);//先插入0,因爲x[0]也要算一次
LL ans=0;
for(int i=0; i<n; i++)
{
ans+=ac.query(root,-inf,inf,x[i]-R,x[i]-L);//統計答案
ac.update(root,-inf,inf,x[i]);//將這個值插入後面要用到
}
printf("%lld\n",ans);
}
}
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=7e6+10;
const LL inf=10000000000;
struct AC
{
struct zp
{
int lson,rson;
LL sum;
bool lazy;
} tree[maxn];
int cont;
void init()
{
cont=0;
}
int newnode()
{
tree[cont].lson=tree[cont].rson=-1;
tree[cont].sum=0;
tree[cont].lazy=0;
cont++;
return cont-1;
}
void pushdown(int k)
{
if(tree[k].lazy==1)
{
if(tree[k].lson!=-1)
{
tree[tree[k].lson].lazy=1;
tree[tree[k].lson].sum=0;
}
if(tree[k].rson!=-1)
{
tree[tree[k].rson].lazy=1;
tree[tree[k].rson].sum=0;
}
tree[k].lazy=0;
}
}
void pushup(int k)
{
LL ans=0;
if(tree[k].lson!=-1)
ans+=tree[tree[k].lson].sum;
if(tree[k].rson!=-1)
ans+=tree[tree[k].rson].sum;
tree[k].sum=ans;
}
void update1(int &k,LL l,LL r,LL num,LL cnt)//opt 1
{
if(k==-1) k=newnode();
pushdown(k);
tree[k].sum+=cnt;
if(l==r) return ;
LL mid=(l+r)>>1;
if(num<=mid) update1(tree[k].lson,l,mid,num,cnt);
else update1(tree[k].rson,mid+1,r,num,cnt);
}
void update2(int k,LL l,LL r,LL ql,LL qr)//設置清空標記
{
if(k==-1) return ;
pushdown(k);
if(ql==l&&qr==r)
{
tree[k].lazy=1,tree[k].sum=0;
return ;
}
LL mid=(l+r)>>1;
if(qr<=mid) update2(tree[k].lson,l,mid,ql,qr);
else if(ql>mid) update2(tree[k].rson,mid+1,r,ql,qr);
else
{
update2(tree[k].lson,l,mid,ql,mid);
update2(tree[k].rson,mid+1,r,mid+1,qr);
}
pushup(k);
}
LL query(int k,LL l,LL r,LL ql,LL qr)//查詢區間值
{
if(k==-1) return 0;
pushdown(k);
if(l==ql&&r==qr) return tree[k].sum;
LL mid=(l+r)>>1;
if(qr<=mid) return query(tree[k].lson,l,mid,ql,qr);
else if(ql>mid) return query(tree[k].rson,mid+1,r,ql,qr);
else return query(tree[k].lson,l,mid,ql,mid)+query(tree[k].rson,mid+1,r,mid+1,qr);
}
LL query1(int k,LL l,LL r,LL num)//查詢第num小的數
{
pushdown(k);
if(l==r) return l;
LL mid=(l+r)>>1;
if(tree[k].lson!=-1)
{
if(tree[tree[k].lson].sum>=num)
return query1(tree[k].lson,l,mid,num);
else
return query1(tree[k].rson,mid+1,r,num-tree[tree[k].lson].sum);
}
else
return query1(tree[k].rson,mid+1,r,num);
}
} ac;
int main()
{
int n;
while(~scanf("%d",&n))
{
ac.init();
int root=-1;
for(int i=0; i<n; i++)
{
int opt;
LL num,sum;
scanf("%d%lld",&opt,&num);
switch(opt)
{
case 1:
ac.update1(root,-inf,inf,num,1);
break;
case 2:
sum=ac.query(root,-inf,inf,-inf,num-1);
ac.update2(root,-inf,inf,-inf,num-1);
ac.update1(root,-inf,inf,num,sum);
break;
case 3:
sum=ac.query(root,-inf,inf,num+1,inf);
ac.update2(root,-inf,inf,num+1,inf);
ac.update1(root,-inf,inf,num,sum);
break;
case 4:
printf("%lld\n",ac.query1(root,-inf,inf,num));
break;
case 5:
printf("%lld\n",ac.query(root,-inf,inf,-inf,num-1));
break;
}
}
}
}