离散化+树状数组
1 3 1 1 2 1 2 2 1 1
5
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long int LL;
const int maxn=100100;
int n,sum;
int tree[maxn];
int cnt[1111],cnum[1111][111];
LL b[maxn];
int len;
int lowbit(int x)
{
return x&(-x);
}
void Add(int p)
{
for(int i=p;i<maxn;i+=lowbit(i))
tree[i]++;
}
int Sum(int p)
{
int ret=0;
for(int i=p;i;i-=lowbit(i))
ret+=tree[i];
return ret;
}
void init()
{
len=0; memset(tree,0,sizeof(tree));
}
int main()
{
int T_T;
scanf("%d",&T_T);
while(T_T--)
{
scanf("%d%d",&n,&sum);
sum++;
init();
for(int i=0;i<n;i++)
{
scanf("%d",cnt+i);
for(int j=0;j<cnt[i];j++)
{
scanf("%d",&cnum[i][j]);
b[len++]=cnum[i][j];
}
}
b[len++]=(1LL<<60);
sort(b,b+len);
len=unique(b,b+len)-b;
LL ans=0,nb=0;
/// add first line
for(int i=0;i<cnt[0];i++)
{
int k=lower_bound(b,b+len,cnum[0][i])-b+1;
nb++;
Add(k);
}
/// add other line
for(int i=1;i<n;i++)
{
/// get ans
for(int j=0;j<cnt[i];j++)
{
int m=sum-cnum[i][j];
int k=lower_bound(b,b+len,m)-b;
if(k==len-1) continue;
ans+=nb-Sum(k);
}
/// add this line
for(int j=0;j<cnt[i];j++)
{
int k=lower_bound(b,b+len,cnum[i][j])-b+1;
nb++;
Add(k);
}
}
cout<<ans<<endl;
}
return 0;
}
原文:http://blog.csdn.net/ck_boss/article/details/41744051