http://blog.youkuaiyun.com/libin66/article/details/52497502
水平还是太差了,以前一直做水题,然而网络赛的题都是有些难度的,自己做了一个下午才AC。
比赛时有一个想法,实现了,理论上也不会超时,但是还是TLE了,不知道为啥。
具体方法就是写一个表达式树,每个数字代表一个节点,从而此数字后面的所有数字都是它的子节点。从后往前枚举每个数字,对这个数字后面的所有数字按ai进行间接排序,然后upper_bound坐标一减就是答案。O(nlogn),但超时了,然后就没再研究了。
参考了别人的方法,一直TLE或WA,而且找不到错,重写了几遍才AC,至少说明了TLE不一定是方法不对,也很有可能是你哪里细节没写好然后就死循环了?
他们的方法就是一边dfs一边维护线段树,同时计算答案,还用了离散化。具体怎么做不好说,看代码比较好。
两份代码:
一份是超时的那个。
一份是AC的。
#include<bits/stdc++.h>
#define maxn 100010
using namespace std;
typedef long long ll;
ll N,k;
ll a[maxn];
ll id[maxn];
ll last[maxn];
ll r[maxn];
vector<ll>tree;
vector<ll>MAP[maxn];
void dfs(int u)
{
tree.push_back(u);
for(unsigned int i=0;i<MAP[u].size();i++)
dfs(MAP[u][i]);
last[u]=tree.size()-1;
}
bool cmp(ll x,ll y)
{
return a[tree[x]]<a[tree[y]];
}
ll ub(ll* A,ll x,ll y,ll v)
{
ll m;
while(x<y)
{
m=x+(y-x)/2;
if(a[tree[A[m]]]<=v) x=m+1;
else y=m;
}
return x;
}
int main()
{
ll T;
scanf("%I64d",&T);
while(T--)
{
tree.clear();
tree.push_back(0);
memset(id,0,sizeof(id));
scanf("%I64d %I64d",&N,&k);
for(ll i=1;i<=N;i++)
{
scanf("%I64d",&a[i]);
r[i]=i;
MAP[i].clear();
}
ll u,v;
for(ll i=1;i<N;i++)
{
scanf("%I64d %I64d",&u,&v);
MAP[u].push_back(v);
id[v]++;
}
for(ll i=1;i<=N;i++)
if(id[i]==0)
dfs(i);
ll ans=0;
for(ll i=N;i>=1;i--)
{
sort(r+i+1,r+last[tree[i]]+1,cmp);
//ans+=upper_bound(r+i+1,r+last[tree[i]]+1,k/a[tree[i]])-r-i-1;
ans+=ub(r,i+1,last[tree[i]]+1,k/a[tree[i]])-i-1;
}
printf("%I64d\n",ans);
}
return 0;
}
#include<bits/stdc++.h>
#define maxn 100010
using namespace std;
typedef long long ll;
ll tree[maxn<<3];
void A(ll l,ll r,ll now,ll pos,ll val)
{
if(l==r) {tree[now]+=val;return;}
ll m=(l+r)>>1;
ll ls=now<<1;
ll rs=ls|1;
if(pos<=m) A(l,m,ls,pos,val);
else A(m+1,r,rs,pos,val);
tree[now]=tree[ls]+tree[rs];
}
ll Q(ll l,ll r,ll now,ll ql,ll qr)
{
if(l>=ql&&r<=qr) return tree[now];
ll m=(l+r)>>1;
ll ls=now<<1;
ll rs=ls|1;
if(qr<=m) return Q(l,m,ls,ql,qr);
else if(ql>m) return Q(m+1,r,rs,ql,qr);
else return Q(l,m,ls,ql,qr)+Q(m+1,r,rs,ql,qr);
}
ll a[maxn];
ll b[maxn<<1];
ll id[maxn];
ll N,k,L,ans;
vector<ll>MAP[maxn];
void dfs(int u)
{
ll pos=lower_bound(b+1,b+1+L,k/a[u])-b;
ans+=Q(1,L,1,1,pos);
pos=lower_bound(b+1,b+1+L,a[u])-b;
A(1,L,1,pos,1);
for(unsigned int i=0;i<MAP[u].size();i++) dfs(MAP[u][i]);
A(1,L,1,pos,-1);
}
int main()
{
ll T;
scanf("%I64d",&T);
while(T--)
{
scanf("%I64d %I64d",&N,&k);
memset(id,0,sizeof(id));
memset(tree,0,sizeof(tree));
for(ll i=1;i<=N;i++)
{
scanf("%I64d",&a[i]);
b[i]=a[i];
b[i+N]=k/a[i];
MAP[i].clear();
}
sort(b+1,b+1+2*N);
L=unique(b+1,b+1+2*N)-b-1;
ll u,v;
for(ll i=1;i<N;i++)
{
scanf("%I64d %I64d",&u,&v);
MAP[u].push_back(v);
id[v]++;
}
ans=0;
for(ll i=1;i<=N;i++)
if(id[i]==0)
dfs(i);
printf("%I64d\n",ans);
}
return 0;
}