题意: 有二元组集{(a,b)}和三元组集{(c,d,e)}。当 (a,b)和(c,d,e) 满足 b==e 时,(a,c,d)组成新的三元组集 C {(a,b,c)}。
计算三元组集 C 中 满足 不存在除与本身相等外满足(u>=a,v>=b,w>=c)的三元组(u,v,w) 的三元组(a,b,c)。
思路:
自己写的时候完全没有思路啊~
参考了http://async.icpc-camp.org/d/227-shenyang-2015-i
和http://blog.csdn.net/beihai2013/article/details/49588259
首先对于二元组集{(a,b)},预处理出 b 对应的最大 a 值和个数。
接着与三元组集{(c,d,e)}结合组成新的三元组C {(a,b,c,t)}(其中t表示这样的三元组的个数)。
对于新三元组集C {(a,b,c)},预处理出 a 对应的极大值 (c,d)值和个数 (对 b 进行从大到小排序,相同的b只取最大 c 值并记录个数,然后根据 b 从大到小遍历一遍,之前的 c >= 当前位置的 c,那么这个三元组(a,b,c)是无效的)。现在,对于每个三元组(a,b,c),都是关于 a 的局部最大,所以对a从大到小排序,遍历,用二维树状数组处理是否存在大于等于当前(b,c)的三元组(此时不会出现(a,b,c)完全相等,所以如果出现(b,c)相等,说明之前出现的那个的 a 更大)。边算边加答案,但这样的实现有点麻烦,所以没有用这种方法。
重新考虑一下,对a从大到小排序,遍历,用二维树状数组处理是否存在大于等于当前(b,c)的三元组。如果对三元组按a,b,c分别作为第一,二,三关键字进行排序,那么如果对三元组从大到小进行遍历并用二维树状数组处理会有什么问题? 如果(a1,b1,c1)和(a2,b2,c2)满足 b1==b2&&c1==c2,那么我们无法知道是否 a1==a2。于是我们只要先把重复的叠起来,再这样做就可以了!!
#include
#include
#include
#include
#include
#include
#include
#include
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int MAXN=1e5+5;
int mx[MAXN],cnt[MAXN];
struct _ABC
{
int a,b,c,t;
bool operator < (const struct _ABC &k) const{
if(a!=k.a) return a>k.a;
else if(b!=k.b) return b>k.b;
else return c>k.c;
}
}abc[MAXN];
int BIT2d[1003][1003];
void add(int x,int y)
{
while(x<1001)
{
for(int i=y;i<1001;i+=i&-i)
BIT2d[x][i]+=1;
x+=x&-x;
}
}
int sum(int x,int y)
{
int rt=0;
while(x)
{
for(int i=y;i;i-=i&-i)
rt+=BIT2d[x][i];
x-=x&-x;
}
return rt;
}
int main(void)
{
int t,ti=0;
scanf("%d",&t);
while(++ti<=t)
{
int n,m;LL ans=0;
scanf("%d%d",&n,&m);
ms(mx);ms(cnt);
for(int i=0;iint a,b;
scanf("%d%d",&a,&b);
if(mx[b]1;
else if(mx[b]==a) ++cnt[b];
}
n=0;
for(int i=0;iint c,d,e;
scanf("%d%d%d",&c,&d,&e);
if(mx[e])
abc[n].a=mx[e],abc[n].b=c,abc[n].c=d,
abc[n++].t=cnt[e];
}
sort(abc,abc+n);
ms(BIT2d);
m=1;
for(int i=1;iif(abc[i].a==abc[m-1].a&&abc[i].b==abc[m-1].b&&abc[i].c==abc[m-1].c)
abc[m-1].t+=abc[i].t;
else abc[m++]=abc[i];
for(int i=0;iif(sum(1000,1000)-sum(abc[i].b-1,1000)
-sum(1000,abc[i].c-1)+sum(abc[i].b-1,abc[i].c-1)==0)
ans+=abc[i].t;
add(abc[i].b,abc[i].c);
}
printf("Case #%d: %I64d\n",ti,ans );
}
return 0;
}