HDOJ 5101 Select 树状数组

离散化+树状数组

Select

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1149    Accepted Submission(s): 329

Problem Description

One day, Dudu, the most clever boy, heard of ACM/ICPC, which is a very interesting game. He wants to take part in the game. But as we all know, you can‘t get good result without teammates.

So, he needs to select two classmates as his teammates.

In this game, the IQ is very important, if you have low IQ you will WanTuo. Dudu‘s IQ is a given number k. We use an integer v[i] to represent the IQ of the ith classmate.

The sum of new two teammates‘ IQ must more than Dudu‘s IQ.

For some reason, Dudu don‘t want the two teammates comes from the same class.

Now, give you the status of classes, can you tell Dudu how many ways there are.

Input

There is a number T shows there are T test cases below. (T≤20)

For each test case , the first line contains two integers, n and k, which means the number of class and the IQ of Dudu. n ( 0≤n≤1000 ),
k( 0≤k<231 ).

Then, there are n classes below, for each class, the first line contains an integer m, which means the number of the classmates in this class, and for next m lines, each line contains an integer v[i], which means there is a person whose iq is v[i] in this class.
m( 0≤m≤100 ),
v[i]( 0≤v[i]<231 )

Output

For each test case, output a single integer.

Sample Input

1
3 1
1 2
1 2
2 1 1

Sample Output

5

Source

BestCoder Round #17

#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;
}
时间: 2024-10-23 20:22:31

HDOJ 5101 Select 树状数组的相关文章

hdu 5101 Select(树状数组)

题目链接:hdu5101 Select 题目大意:N和K,给定若干组数,要从从不同组中选出连个数和大于K,问说有多少种组成方案. 解题思路:树状数组维护,将所有的数离散化掉对应成树状数组的下标,每次先计算一组,然后再将该组的元素插入到 树状数组中. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int m

hdoj 4911 Inversion 树状数组+离散化

题意:给你n个可以重复的无序数列,问经过k次相邻交换后最少还有多少对逆序数 求逆序对可以用树状数组来做,对于重复的元素,可能在sort的时候交换编号 求和的时候要注意去重,还有一种方法就是稳定排序stable_sort #include<string.h> #include<stdio.h> #include<algorithm> using namespace std; #define ll __int64 #define N 100000+10 struct ln{

HDU 5101 Select --离散化+树状数组

题意:n 组,每组有一些值,求 在不同的两组中每组选一个使值的和大于k的方法数. 解法:n * Cnt[n] <= 1000*100 = 100000, 即最多10^5个人,所以枚举每个值x,求他的后面那些组中有多少数大于 k-x即可, 求有多少数大于k-x可以先求有多少数小于等于k-x,然后总数减一下即可. 可以用树状数组求. 先把所有数离散地存入一个树状数组中,然后每次枚举完一组的数后,将这组的数去掉. 代码: #include <iostream> #include <cst

【HDOJ 5654】 xiaoxin and his watermelon candy(离线+树状数组)

pid=5654">[HDOJ 5654] xiaoxin and his watermelon candy(离线+树状数组) xiaoxin and his watermelon candy Time Limit: 4000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 233    Accepted Submission(s): 61 Problem Des

线段树(单点更新)/树状数组 HDOJ 1166 敌兵布阵

题目传送门 1 /* 2 线段树基本功能:区间值的和,修改某个值 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #define lson l, m, rt << 1 7 #define rson m+1, r, rt << 1|1 8 9 const int MAX_N = 50000 + 10; 10 int sum[MAX_N<<2]; 11 12 void pushup(int rt) //

hdoj 1892(二维树状数组)

Problem H Time Limit : 5000/3000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total Submission(s) : 8   Accepted Submission(s) : 3 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description Now I am leaving hust acm. In

线段树+树状数组+贪心 HDOJ 5338 ZZX and Permutations

题目传送门 1 /* 2 题意:不懂... 3 线段树+树状数组+贪心:贪心从第一位开始枚举,一个数可以是循环节的末尾或者在循环节中,循环节(循环节内部是后面的换到前面,最前面的换到最后面).线段树维护最大值,树状数组维护区间是否是循环节,查找前面最左边不是循环节的可用二分.我还是云里雾里的,看懂了网上的解题报告但还是不是完全明白题意:( 4 详细解释:http://blog.csdn.net/qq_24451605/article/details/47173933 5 */ 6 /******

HDOJ 5147 Sequence II 树状数组

树状数组: 维护每一个数前面比它小的数的个数,和这个数后面比他大的数的个数 再枚举每个位置组合一下 Sequence II Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 121    Accepted Submission(s): 58 Problem Description Long long ago, there is a seq

hdoj 1556 Color the ball(树状数组)

Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗? Input 每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <=