给你n个二元组<a,b>, m个三元组<c,d,e>. 如果d = e,那么<a,c,d>会组成一个新的三元组集合G.
问G中有多少个三元组在凸点.(没有其它三元组比它大)
要注意去重. 因为要求没有其它三元组比它大. 如果同一个b有多个a,那么只需要取最大的即可.
然后通过排序可以解决第一位a. 剩下两位c,d则可以通过二维树状数组来维护是否是最大值.
三元组G中相同的合并.
极其无奈 wa了无数次
#include <bits/stdc++.h> using namespace std; #define ll long long const int N=1000; const int maxn=1e5+100; int sum[N+10][N+10]; int t,n,m; struct node{ int x,y,z,num; }a[maxn],c[maxn],cc[maxn]; vector<node>b[maxn]; bool cmp(const node &l,const node &r) { if(l.z==r.z) { if(l.x==r.x) return l.y>r.y; else return l.x>r.x; } else return l.z>r.z; } int lowbit(int x) {return x&(-x);} int update(int x,int y,int val) { for(int i=x;i<=N;i+=lowbit(i)) for(int j=y;j<=N;j+=lowbit(j)) sum[i][j]+=val; } int query(int x,int y) { int ans=0; for(int i=x;i>0;i-=lowbit(i)) for(int j=y;j>0;j-=lowbit(j)) ans+=sum[i][j]; return ans; } int main() { freopen("in.txt","r",stdin); int val,cas=0; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); memset(a,0,sizeof a); memset(c,0,sizeof c); for(int i=1;i<=m;i++) b[i].clear(); for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); if(x==a[y].x) a[y].num++; else if(x>a[y].x) { a[y].x=max(a[y].x,x); a[y].num=1; } } int cnt=0; for(int i=1;i<=m;i++) { node g; int z; scanf("%d%d%d",&g.x,&g.y,&z); if(a[z].num>0) { cnt++; c[cnt].x=g.x; c[cnt].y=g.y; c[cnt].z=a[z].x; c[cnt].num=a[z].num; } } sort(c+1,c+cnt+1,cmp); int nn=1; for(int i=2;i<=cnt;i++) { if(c[nn].x==c[i].x&&c[nn].y==c[i].y&&c[nn].z==c[i].z) { c[nn].num+=c[i].num; } else { c[++nn]=c[i]; } } ll ans=0; memset(sum,0,sizeof sum); for(int i=1;i<=nn;i++) { int x=c[i].x,y=c[i].y,num=c[i].num; // if(x==c[i-1].x&&y==c[i-1].y&&c[i].z==c[i-1].z) // continue; // cout<<query(N,N)<<endl; // cout<<query(x-1,N)<<endl; // cout<<query(N,y-1)<<endl; // cout<<query(x-1,y-1)<<endl; // cout<<c[i].z<<"--"<<x<<"--"<<y<<endl; if(query(N,N)-query(x-1,N)-query(N,y-1)+query(x-1,y-1)==0) ans+=1ll*num; update(x,y,1); // cout<<ans<<endl; // puts("-------------------------"); } printf("Case #%d: %lld\n",++cas,ans); } return 0; }