题意:给一个
n
个二元组:
设所有的二元组,三元组组合后得到的新的三元组的集合是
C
。
求
分析:学习的这里的做法
首先,对于二元组,相同的
b
取最大的
扫一遍所有的三元组:二位线段树维护
代码:
#include <bits/stdc++.h>
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
using namespace std;
typedef vector <int> VT;
const int maxn = 100010;
const int maxm = 1010;
int b[maxn],cnt_b[maxn];
struct Point{
int a,c,d;
int cnt;
Point() {}
Point(int x,int y,int z,int k): a(x),c(y),d(z),cnt(k) {}
bool operator < (const Point& rhs) const{
if(a == rhs.a){
if(c == rhs.c) return d > rhs.d;
return c > rhs.c;
}
return a > rhs.a;
}
bool operator == (const Point& rhs) const{
if(a == rhs.a && c == rhs.c && d == rhs.d) return true;
return false;
}
}point[maxn],pp[maxn];
int n,m;
void init(){
scanf("%d%d",&n,&m);
FOR(i,0,maxn) b[i] = cnt_b[i] = 0;
int x,y,z;
FOR(i,0,n){
scanf("%d%d",&x,&y);
if(b[y] == x) cnt_b[y] ++;
else if(b[y] < x) {b[y] = x; cnt_b[y] = 1;}
}
n = 0;
FOR(i,0,m){
scanf("%d%d%d",&x,&y,&z);
if(b[z]){
pp[++n] = Point(b[z],x,y,cnt_b[z]);
}
}
sort(pp+1,pp+n+1);
int len = 0;
point[++len] = pp[1];
FOR(i,2,n+1){
if(point[len] == pp[i]){
point[len].cnt += pp[i].cnt;
}
else{
point[++len] = pp[i];
}
}
n = len;
}
int tree[maxm][maxm];
int lowbit(int x) {return x & (-x);}
void Modify(int x,int y,int val){
int rt_x = x,rt_y = y;
for(rt_x = x;rt_x < maxm;rt_x += lowbit(rt_x)){
for(rt_y = y;rt_y < maxm;rt_y += lowbit(rt_y)){
tree[rt_x][rt_y] += val;
}
}
}
int query(int x,int y){
int res = 0;
int rt_x,rt_y;
for(rt_x = x;rt_x;rt_x -= lowbit(rt_x)){
for(rt_y = y;rt_y ;rt_y -= lowbit(rt_y)){
res += tree[rt_x][rt_y];
}
}
return res;
}
void work(){
FOR(i,0,maxm)
FOR(j,0,maxm) tree[i][j] = 0;
int ans = 0;
FOR(i,1,n+1){
if(!query(1001-point[i].c,1001-point[i].d)){
ans += point[i].cnt;
}
Modify(1001-point[i].c,1001-point[i].d,1);
}
printf("%d\n",ans);
}
int main()
{
//freopen("test.in","r",stdin);
int T,tCase = 0; scanf("%d",&T);
while(T--){
printf("Case #%d: ",++tCase);
init();
work();
}
return 0;
}