首先还是要清楚一下堆操作的代码,毕竟线段树打多了,打堆的时候总会往线段树方向靠近
首先是建堆:
D=1;
for(;D<maxn+2;D<<=1);
然后给堆赋予值就可以了
查找区间段的和:
int query(int s,int t)
{
int i=D+s-1,j=D+t+1,ans=0;
for(;i^j^1;i>>=1,j>>=1){
if(~i&1) ans+=sum[i^1];
if(j&1) ans+=sum[j^1];
}
return ans;
}
更新操作:
void update(int i)
{
for(;i^1;i>>=1)
sum[i>>1]=sum[i]+sum[i^1];
}
之前也做了一道star level的题写成了博客,这里继续来写一遍,就是问对于一个星星的位置,比其x小于等于和y小于等于的点有多少个
这里我们所采取的是先进行一维上的排序,然后排好序后用另一维度来建树
如星星的题目已经以y的大小先后排好序了,那我们就省事了
我们从第一个节点不断添加进去,来找比它x小的数有几个,每次添加一个x,都要tree[D+x]++,再进行更新操作,因为后面的点是绝对不会影响到前面的点的
所以是可以这样做的:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define N 32000 6 int sum[N<<2],D; 7 void push_up(int i) 8 { 9 for(;i^1;i>>=1) 10 sum[i>>1]=sum[i]+sum[i^1]; 11 } 12 int query(int s,int t) 13 { 14 int i=D+s-1,j=D+t+1,ans=0; 15 for(;i^j^1;i>>=1,j>>=1) 16 { 17 if(~i&1) ans+=sum[i^1]; 18 if(j&1) ans+=sum[j^1]; 19 } 20 return ans; 21 } 22 int main() 23 { 24 int n,a[15005],b[15005],ans[15005],maxn=0; 25 scanf("%d",&n); 26 for(int i=1;i<=n;i++){ 27 scanf("%d%d",&a[i],&b[i]); 28 a[i]++; 29 maxn=max(maxn,a[i]); 30 } 31 memset(sum,0,sizeof(sum)); 32 D=1; 33 for(;D<maxn+2;D<<=1); 34 for(int i=1;i<=n;i++){ 35 ans[i]=query(1,a[i]); 36 sum[a[i]+D]++; 37 //printf("%d,%d\n",a[i],sum[a[i]+D]); 38 push_up(a[i]+D); 39 } 40 int lev[15005]; 41 memset(lev,0,sizeof(lev)); 42 for(int i=1;i<=n;i++) lev[ans[i]]++; 43 for(int i=0;i<n;i++) printf("%d\n",lev[i]); 44 return 0; 45 }
第二题:
这道题目也是两个维度,不过如果出现一样的值的话,者之间是不算谁比谁大的,这是跟星星不一样的地方
所以我们排好序后,每次添加点进入的时候还需要判断是否与前一个点值完全相同,如果相同不访问,直接继承前面一个点的值就可以了,然后再做更新
同时星星的点是题目本身按顺序给出的,而这里是乱序的,我们需要事先排好序然后不断添入点
我采取的方法是,建立结构体,除2维的数据外,还需记录id号,不然没法记录每个位置比别人大的个数
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define N 300005 6 int sum[N<<2],D,maxn; 7 struct Edge{ 8 int x,y,id; 9 bool operator<(const Edge &m)const 10 { 11 return x==m.x?y<m.y:x<m.x; 12 } 13 }e[N]; 14 void update(int i) 15 { 16 for(;i^1;i>>=1) 17 sum[i>>1]=sum[i]+sum[i^1]; 18 } 19 int query(int s,int t) 20 { 21 int i=D+s-1,j=D+t+1,ans=0; 22 for(;i^j^1;i>>=1,j>>=1){ 23 if(~i&1) ans+=sum[i^1]; 24 if(j&1) ans+=sum[j^1]; 25 } 26 return ans; 27 } 28 int main() 29 { 30 int n,ans[N]; 31 maxn=0; 32 memset(sum,0,sizeof(sum)); 33 scanf("%d",&n); 34 for(int i=0;i<n;i++){ 35 scanf("%d%d",&e[i].x,&e[i].y); 36 maxn=max(maxn,e[i].y); 37 e[i].id=i; 38 } 39 D=1; 40 for(;D<maxn+2;D<<=1); 41 sort(e,e+n); 42 int k; 43 for(int i=0;i<n;i++){ 44 if(i>1&&e[i].x==e[i-1].x&&e[i].y==e[i-1].y){ 45 } 46 else{ 47 k=query(1,e[i].y); 48 } 49 ans[e[i].id]=k; 50 sum[D+e[i].y]++; 51 update(D+e[i].y); 52 } 53 for(int i=0;i<n;i++) 54 printf("%d\n",ans[i]); 55 return 0; 56 }