版权声明:版权归Ordinarv所有 https://blog.csdn.net/ordinarv/article/details/81912127
题意大意:
给n个集合,求从两个不同集合里面各取一个数使得它们的和大于给定数的方案数。
分析:
1、ans=从所有数里面取两个数的方案数sum-从每个集合里面取两个数的方案数aum(这是关键)
2、后来发现离散一下,然后树状数组统计也行。
但是我算的aum老是结果不对 wa了好久。
主要就是二分出了问题
//wa version:
while(l<=r){
mid=(r+l)/2;
if(iq[i][mid]>tra) r=mid+1;
else l=mid+1;
}
aum+=cls[i]-l;
//ac version:
while(l<r){
mid=(r+l)/2;
if(iq[i][mid]>tra) r=mid;
else l=mid+1;
}
aum+=cls[i]-l;
ac code:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
ll k,n,cls[1100],iq[1100][110],all[110000];
int main() {
int t,cnt;
scanf("%d",&t);
while(t--) {
cnt=-1;
scanf("%lld%lld",&n,&k);
for(int i=0; i<n; i++) {
scanf("%lld",&cls[i]);//each class number of student
for(int j=0; j<cls[i]; j++) {
scanf("%lld",&iq[i][j]);
all[++cnt]=iq[i][j];
}
}
ll sum=0,aum=0;
sort(all,all+cnt+1);
for(int i=0; i<cnt; i++) {
ll r=cnt,l=i+1,mid,tra=k-all[i];
while(l<=r) {
mid=(r+l)/2;
if(all[mid]>tra)
r=mid-1;
else
l=mid+1;
}
sum+=cnt-l+1;//beacuse all array is begin 0-cnt
}
for(int i=0; i<n; i++) {
if(cls[i]<2) continue;
sort(iq[i],iq[i]+cls[i]);
for(int j=0; j<cls[i]-1; j++) {
ll r=cls[i],l=j+1,tra=k-iq[i][j],mid;
while(l<r) {
mid=(r+l)/2;
if(iq[i][mid]>tra) r=mid;
else l=mid+1;
}
aum+=cls[i]-l;
}
}
printf("%lld\n",sum-aum);
}
return 0;
}
柱状数组:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <vector>
#include <stack>
#include <string>
#include <ctime>
#include <queue>
#define mem0(a) memset(a, 0, sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define eps 0.0000001
#define lowbit(x) ((x) & -(x))
#define memc(a, b) memcpy(a, b, sizeof(b))
#define x_x(a) ((a) * (a))
#define LL long long
#define DB double
#define pi 3.14159265359
#define MD 10000007
#define INF (int)1e9
#define max(a, b) ((a) > (b)? (a) : (b))
using namespace std;
map<int, int> hash;
int nn, tot, arr[220000], arr0[220000], c[220000], a[1200][120], m[1200];
void init()
{
sort(arr + 1, arr + 1 + tot);
arr0[1] = arr[1];
nn = 1;
hash[arr0[1]] = 1;
for(int i = 2; i <= tot; i++) {
if(arr[i] != arr[i - 1]) {
arr0[++nn] = arr[i];
hash[arr[i]] = nn;
}
}
}
void update(int p, int x)
{
while(p <= nn) {
c[p] += x;
p += lowbit(p);
}
}
void insert(int a[], int n)
{
for(int i = 1; i <= n; i++) {
int tmp = hash[a[i]];
update(tmp, 1);
}
}
int sum(int p)
{
int ans = 0;
while(p) {
ans += c[p];
p -= lowbit(p);
}
return ans;
}
int query(int L, int R)
{
return sum(R) - sum(L - 1);
}
int find(int x)
{
int l = 1, r = nn;
while(l < r) {
int m = (l + r) >> 1;
if(arr0[m] > x) r = m;
else l = m + 1;
}
return l;
}
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int T;
cin>> T;
while(T--) {
hash.clear();
mem0(c);
int n, k;
cin>> n>> k;
tot = 0;
for(int i = 1; i <= n; i++) {
cin>> m[i];
for(int j = 1; j <= m[i]; j++) {
scanf("%d", &a[i][j]);
arr[++tot] = a[i][j];
}
}
init();
insert(a[1], m[1]);
LL ans = 0;
for(int i = 2; i <= n; i++) {
for(int j = 1; j <= m[i]; j++) {
int tmp = find(k - a[i][j]);
ans += query(tmp, nn);
}
insert(a[i], m[i]);
}
cout<< ans<< endl;
}
return 0;
}