HDU4417 Super Mario 主席树 / 树状数组

给出n个数,m个询问,每次查询在[L,R]中≤x的数有多少个.

在线做的话是主席树模板了

离线做将查询按位置先后排序

逐个向树状数组中插入数,并回答询问(类似查询逆序对)

最后再按时间排回来

都需要离散化.

因为是小于等于,二分的时候要upper_bound.坑死了

多组数据初始化坑爹啊。。

主席树

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x))
using namespace std;
const int N=100005;
struct Node{
	int l,r,sum;
}t[N*36];
vector<int> v;
int n,m,a[N],rt[N],cnt,sz;
int getid(int x)
{
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void update(int l,int r,int &x,int y,int pos)
{
	t[++cnt]=t[y];t[cnt].sum++;x=cnt;
	if(l==r)return;
	int mid=(l+r)>>1;
	if(pos<=mid)
	  update(l,mid,t[x].l,t[y].l,pos);
	else
	  update(mid+1,r,t[x].r,t[y].r,pos);
}
int query(int l,int r,int x,int y,int K)
{
	if(l==r)return t[y].sum-t[x].sum;
	int mid=(l+r)>>1;
	int sum=t[t[y].l].sum-t[t[x].l].sum;
	if(mid>=K)
	  return query(l,mid,t[x].l,t[y].l,K);
	else
	  return query(mid+1,r,t[x].r,t[y].r,K)+sum;
}
int res[N],tot;
void solve()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	  scanf("%d",&a[i]),v.push_back(a[i]);
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
	sz=v.end()-v.begin();
	for(int i=1;i<=n;i++)
	  update(1,sz,rt[i],rt[i-1],getid(a[i]));
	int p,q,h,tmp;tot=0;
	while(m--)
	{
		scanf("%d%d%d",&p,&q,&h);
		tmp=upper_bound(v.begin(),v.end(),h)-v.begin();
		//printf("%d ",tmp);
		int ret1=query(1,sz,rt[p],rt[q+1],tmp);
		//res[++tot]=ret1;
		if(tmp)res[++tot]=ret1;
		else res[++tot]=0;
	}
	for(int i=1;i<=tot;i++)printf("%d\n",res[i]);
}
void init()
{
	for(int i=0;i<=cnt;i++)
	  rt[i]=0,t[i].l=t[i].r=t[i].sum=0;
	cnt=0;
	v.erase(v.begin(),v.end());
}
int main()
{
	//freopen("4417.in","r",stdin);
    //freopen("4417.ans","w",stdout);
	int cas;scanf("%d",&cas);
	for(int t=1;t<=cas;t++){
		init();printf("Case %d:\n",t);solve();	
	}
	return 0;
}


离线树状数组

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define LL long long
#define clr(x,i) memset(x,i,sizeof(x))
#define lowbit(x) (x&(-x))
using namespace std;
const int N=100005;
struct Q{
	int pos,x,id,ans;
}q[N*4];
int n,m,a[N],c[N],tot;
bool cmp1(const Q &a,const Q &b)
{
	return a.pos<b.pos;
}
bool cmp2(const Q &a,const Q &b)
{
	return a.id==b.id ? a.pos<b.pos : a.id<b.id;
}
vector<int> v;
inline int getid(int x)
{
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
inline void Add(int x)
{
	while(x<=n){
		c[x]++;x+=lowbit(x);
	}
}
inline int ask(int x)
{
	int ret=0;
	while(x){
		ret+=c[x];x-=lowbit(x);
	}
	return ret;
}
void solve()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	  scanf("%d",&a[i]),v.push_back(a[i]); 
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
	int x,y,K;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&y,&K);
		x++;y++;
		q[++tot].pos=x-1;q[tot].x=K;q[tot].id=i;
		q[++tot].pos=y;q[tot].x=K;q[tot].id=i;
	}
	sort(q+1,q+tot+1,cmp1);
	int now=0,ans,val;
	for(int i=1;i<=tot;i++)
	{
		while(q[i].pos>now)
		  Add(getid(a[++now]));
		val=upper_bound(v.begin(),v.end(),q[i].x)-v.begin();
		q[i].ans=ask(val);
	}
	sort(q+1,q+tot+1,cmp2);
	for(int i=1;i<=m;i++)
	{
		ans=q[i*2].ans-q[i*2-1].ans;
		printf("%d\n",ans);
	}
}
void init()
{
	v.erase(v.begin(),v.end());
	tot=0;
	for(int i=0;i<=n;i++)c[i]=0;
}
int main()
{
	//freopen("4417.in","r",stdin);
    //freopen("4417.out","w",stdout);
	int cas;scanf("%d",&cas);
	for(int t=1;t<=cas;t++){
		init();printf("Case %d:\n",t);solve();
	}
	return 0;
}



猜你喜欢

转载自blog.csdn.net/wolf_reiser/article/details/78787067