首页 > 代码库 > 几个树状数组的简单题
几个树状数组的简单题
#include<iostream>
#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
#include<memory.h>
#include<string.h>
#include<cmath>
#include<map>
#include<set>
#define INF 0x3f3f3f3f
#define PII pair<int,int>
#define MOD 1000000000
#define MAX_N 1000
using namespace std;
int n,m,w,x,y,tmp;
int xx[100005];
int a[100005];
int ans[100005];
int max_n=0;
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int res=0;
while(x)
{
res+=a[x];
x-=lowbit(x);
}
return res;
}
void add(int x)
{
while(x<=max_n)
{
a[x]++;
x+=lowbit(x);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
xx[i]=x+1;
max_n=max(x+1,max_n);
}
for(int i=1;i<=n;i++)
{
int t=sum(xx[i]);
add(xx[i]);
ans[t]++;
}
for(int i=0;i<=n-1;i++)
cout<<ans[i]<<endl;
return 0;
}
#include<iostream>
#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
#include<memory.h>
#include<string.h>
#include<cmath>
#include<map>
#include<set>
#define INF 0x3f3f3f3f
#define PII pair<int,int>
#define MOD 1000000000
#define MAX_N 1000
using namespace std;
int n,m,w,x,y,tmp;
int xx[100005];
int a[100005];
int ans[100005];
int max_n=0;
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int res=0;
while(x)
{
res+=a[x];
x-=lowbit(x);
}
return res;
}
void add(int x,int num)
{
while(x<=n)
{
a[x]+=num;
x+=lowbit(x);
}
}
int main()
{
//cout<<6+lowbit(6)<<endl;
memset(a,0,sizeof(a));
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x>>y;
//xx[i]=x;
add(x,1);
add(y+1,-1);
//max_n=max(x,max_n);
}
for(int i=1;i<=n;i++)
if(i!=n)
cout<<sum(i)<<" ";
else
cout<<sum(i)<<endl;
//cout<<res<<endl;
return 0;
}
一次有效的交换意味着什么呢?
为了使序列有序,一次有效的交换应该是后一个较小的数与他前一个较大的数交换,那么单独一个数字的交换次数,应该是这个数字前面比它大的数字的个数。
#include<iostream>
#include<algorithm>
#include<memory.h>
using namespace std;
long long a[500005];
long long b[500005];
long long c[500005];
long long n,t;
long long lowbit(long long x)
{
return x&(-x);
}
long long sum(long long x)
{
long long res=0;
while(x)
{
res+=c[x];
x-=lowbit(x);
}
return res;
}
void add(long long x)
{
while(x<=n)
{
c[x]++;
x+=lowbit(x);
}
}
int main()
{
memset(c,0,sizeof(c));
cin>>n;
for(long long i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i];
}
sort(a+1,a+1+n);
long long res=0;
for(long long i=1;i<=n;i++)
{
//index = 小于b[i]的元素个数+1
//即b[i] 被映射成了 index
long long index=lower_bound(a+1,a+1+n,b[i])-a;
long long upper_num=i-1-sum(index-1);
add(index);
res+=upper_num;
}
cout<<res<<endl;
return 0;
}
如果我们知道最后一个人,他前面有 i 个比他小的编号,那么他的编号一定是 i+1。那么我们是不是可以从后往前来确定每个人的编号呢。
#include<iostream>
#include<stdio.h>
#include<memory.h>
using namespace std;
int a[500005];
int c[500005];
int flag[500005];
int res[500005];
int n,t;
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int res=0;
while(x)
{
res+=c[x];
x-=lowbit(x);
}
return res;
}
void add(int x,int num)
{
while(x<=n)
{
c[x]+=num;
x+=lowbit(x);
}
}
int main()
{
memset(c,0,sizeof(c));
memset(flag,0,sizeof(flag));
scanf("%d",&n);
for(int i=2;i<=n;i++)
scanf("%d",&a[i]);
//最后一个点的编号
res[n]=a[n]+1;
add(res[n],1);
flag[res[n]]=1;
for(int i=n-1;i>1;i--)
{
//初始位置
int t=a[i]+1;
int l=0,r=n,pianyi;
//二分枚举偏移量
while(l<=r)
{
int mid=(l+r)>>1;
if(mid+t>n)
{
mid=n-t;
r=2*(n-t)-l;
}
int k=sum(mid+t);
if(mid>k)
{
r=mid-1;
}
if(mid<k)
{
l=mid+1;
}
if(mid==k)
{
pianyi=mid;
r=mid-1;
}
}
res[i]=t+pianyi;
flag[res[i]]=1;
add(res[i],1);
}
for(int i=1;i<=n;i++)
{
if(!flag[i])
{
res[1]=i;
break;
}
}
for(int i=1;i<=n;i++)
printf("%d\n",res[i]);
return 0;
}
几个树状数组的简单题
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。