(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
题意:传送门
原题目描述在最下面。
给出n个二元组
(a,b)
(
a
,
b
)
,m个三元组
(c,d,e)
(
c
,
d
,
e
)
,由
b=e
b
=
e
得到一个新的三元组
(a,c,d)
(
a
,
c
,
d
)
,求最大新三元组集合,满足对于三元组
(a,d,e)
(
a
,
d
,
e
)
不存在三元组
(u,v,w)
(
u
,
v
,
w
)
使得
u≥a,v≥d,w≥e.
u
≥
a
,
v
≥
d
,
w
≥
e
.
数据范围:
n≤100000,m≤100000,a,b,e≤100000,c,d≤1000
n
≤
100000
,
m
≤
100000
,
a
,
b
,
e
≤
100000
,
c
,
d
≤
1000
参考思路:here
思路:
本题十分类似类似 poj2352 p o j 2352 ,只不过模型由二维变成了三维。由一维树状数组优化变成了二维树状数组优化。
显然
(a,b)
(
a
,
b
)
对于同样的
b
b
只有最大的只有用的,所以读入时只保留最大的
a
a
并记录次数。
三元组也只保留能满足
e=b
e
=
b
的。对新的三元组
(a,c,d)
(
a
,
c
,
d
)
按照
a,c,d
a
,
c
,
d
的顺序从大到小排序。
a≤10000,c,d≤1000
a
≤
10000
,
c
,
d
≤
1000
一维从大到小枚举
a
a
,用二维树状数组记录求和,每次先检验
(c,d)到(1000,1000)
(
c
,
d
)
到
(
1000
,
1000
)
矩阵内是否出现过一个三元组。若没出现就累加数量。
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<assert.h>
#include<bitset>
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x)&(-(x))
#define all(x) (x).begin(),(x).end()
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int N = (int)1e5 +107;
int n, m, a,b,c,d,e;
LL da[1010][1010];
int ba[N],cnt[N];
struct lp{
int c,d,e;
LL v;//记录出现次数
lp(){}
lp(int x,int y,int z,LL a){
c=x;d=y;e=z;v=a;
}
}cw[N];
bool cmp(lp &a,lp &b){
if(a.c!=b.c) return a.c<b.c;
if(a.d!=b.d) return a.d<b.d;
return a.e<b.e;
}
void add(int x,int y,LL c){
for(int i = x; i<= 1005; i += lowbit(i)){
for(int j = y;j <= 1005; j += lowbit(j)){
da[i][j] += c;
}
}
}
LL query(int x,int y){
LL ans = 0;
for(int i = x; i; i -= lowbit(i)){
for(int j = y; j; j -= lowbit(j)){
ans += da[i][j];
}
}
return ans;
}
LL ask(int x1,int y1,int x2,int y2){
return query(x2,y2)-query(x1-1,y2)-query(x2,y1-1)+query(x1-1,y1-1);
}
//控制一维单调变化,另两维二维树状数组求和优化
//类似poj2352
int main(){
#ifndef ONLINE_JUDGE
freopen("E://ADpan//in.in", "r", stdin);
//freopen("E://ADpan//out.out", "w", stdout);
#endif
int tim;
scanf("%d", &tim);
int tc=0;
while(tim--){
scanf("%d%d",&n,&m);
memset(ba,-1,sizeof(ba));
memset(cnt,0,sizeof(cnt));
for(int i=0;i<n;++i){
scanf("%d%d",&a,&b);
if(a>ba[b]){
ba[b]=a;
cnt[b]=1;
}else if(a==ba[b])cnt[b]++;
}
int num=0;
for(int i=0;i<m;++i){
scanf("%d%d%d",&c,&d,&e);
if(ba[e]!=-1){
cw[num++]=lp(ba[e],c,d,cnt[e]);
}
}
sort(cw,cw+num,cmp);
n=0;
for(int i=1;i<num;++i){
if(cw[i].e==cw[n].e&&cw[i].c==cw[n].c&&cw[i].d==cw[n].d){
cw[n].v+=cw[i].v;
}else cw[++n]=cw[i];
}
printf("Case #%d: ", ++tc);
memset(da,0,sizeof(da));
LL ans=0;
for(int i=n;i>=0;--i){
if(!ask(cw[i].d,cw[i].e,1005,1005))ans+=cw[i].v;
add(cw[i].d,cw[i].e,1LL);
}
printf("%lld\n", ans);
}
return 0;
}