HDU 5877 dfs+ 线段树(或+树状树组)

1、HDU 5877  Weak Pair

2、总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个

3、思路:利用dfs遍历子节点,同时对于每个子节点au,查询它有多少个祖先av满足av<=k/au。

(1)dfs+线段树

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
#define F(i,a,b) for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=,MAX=; LL k,a[N],b[N*];
int n,m,tree[N*],head[N],in[N]; //注:N*8,不是N*4,因为m可能会是n的2倍 struct Edge
{
int to,nexte;
}edge[N*]; int tot;
void AddEdge(int u,int v)
{
edge[tot].to=v;
edge[tot].nexte=head[u];
head[u]=tot++;
} void update(int pos,int l,int r,int ro,int val)
{
if(l==r){
tree[ro]+=val;
return ;
}
int mid=(l+r)>>;
if(pos<=mid)update(pos,l,mid,ro<<,val);
else update(pos,mid+,r,ro<<|,val);
tree[ro]=tree[ro<<]+tree[ro<<|];
} int query(int R,int l,int r,int ro,int L)
{
if(R>=r&&l>=L){ //注:返回条件
return tree[ro];
}
int mid=(l+r)>>;
if(R<=mid)return query(R,l,mid,ro<<,L);
else if(L>mid)return query(R,mid+,r,ro<<|,L);
else return query(mid,l,mid,ro<<,L)+query(R,mid+,r,ro<<|,mid+); //注:要拆分区间
} LL ans;
void dfs(int r)
{
int pos=lower_bound(b+,b++m,a[r])-b; //注:lower_bound(), -b不是-(b+1)
int posk=lower_bound(b+,b++m,k/a[r])-b;
ans+=1ll*query(posk,,m,,);
update(pos,,m,,);
for(int i=head[r];i!=-;i=edge[i].nexte){
dfs(edge[i].to); //利用dfs序遍历子孙
}
update(pos,,m,,-);
} int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%I64d",&n,&k);
FF(i,,n){
scanf("%I64d",&a[i]);
b[i]=a[i];
}
m=n;
FF(i,,n) b[++m]=k/a[i];
sort(b+,b++m); //排序,离散基础
m=unique(b+,b++m)-(b+); //注:unique(), -(b+1)不是-b mes(head,-);
int u,v;
mes(in,);
ans=tot=;
FF(i,,n-){
scanf("%d%d",&u,&v);
AddEdge(u,v);
in[v]++;
}
mes(tree,);
FF(i,,n){
if(!in[i]){
dfs(i);break;
}
}
printf("%I64d\n",ans);
} return ;
}

(2)dfs+树状树组

这个刚学,还不太懂

#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstdio>
#define F(i,a,b) for (int i=a;i<b;i++)
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int N=,MAX=; LL k,a[N],b[N*],c[N*];
int n,m,head[N],in[N]; struct Edge
{
int to,nexte;
}edge[N*]; int tot;
void AddEdge(int u,int v)
{
edge[tot].to=v;
edge[tot].nexte=head[u];
head[u]=tot++;
} int Lowbit(int x)
{
return x&(-x);
} void update(int pos,int val)
{
for(int i=pos;i<=m;i+=Lowbit(i)){ //注
c[i]+=val;
}
} LL Sum(int posk)
{
LL ans=;
for(int i=posk;i>;i-=Lowbit(i)){ //注
ans+=c[i];
}
return ans;
} LL ans;
void dfs(int r)
{
int pos=lower_bound(b+,b++m,a[r])-b;
int posk=upper_bound(b+,b++m,k/a[r])-(b+); //注:upper_bound(),-(b+1)不是-b
ans+=Sum(posk);
update(pos,);
for(int i=head[r];i!=-;i=edge[i].nexte){
dfs(edge[i].to);
}
update(pos,-);
} int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%I64d",&n,&k);
FF(i,,n){
scanf("%I64d",&a[i]);
b[i]=a[i];
}
m=n;
FF(i,,n) b[++m]=k/a[i];
sort(b+,b++m);
m=unique(b+,b++m)-(b+); mes(head,-);
mes(c,);
int u,v;
mes(in,);
ans=tot=;
FF(i,,n-){
scanf("%d%d",&u,&v);
AddEdge(u,v);
in[v]++;
}
FF(i,,n){
if(!in[i]){
dfs(i);break;
}
}
printf("%I64d\n",ans);
} return ;
}
上一篇:redis批量删除报错误


下一篇:学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))