2015年ACM/ICPC瀋陽賽區 I題(二維樹狀陣列)
阿新 • • 發佈:2018-12-13
題意:給你n(n<=1e5)個正整數二元組<a,b> (1<=a,b<=1e5)
給你m(m<=1e5)個正整數三元組<c,d,e>(1<=c,d<=1e3 1<=e<=1e5)
定義新的三元組等於上述兩個二元組的“積”,運算規則如下:
<a,b> * <c,d,e> =<a,c,d> if b==e
求新的所有三元組中,有多少個三元組在凸點.(沒有其它三元組比它大)
思路:本題的關鍵是資料範圍,注意我紅色標記的部分。
注意到以後,求凸點就比較容易想到二維樹狀陣列了。但是直接暴力相乘兩個二元組的話會爆炸。
注意到新的三元組的定義。也就是說二元組中b相同的,只有最大的a才會對答案有貢獻。(想想是不是)
因此對於每個b,只保留最大的a。相同的累加數量。
這樣和三元組做“積”之後,新的三元組的數量不會超過1e5。然後合併重複的三元組。
然後就是二維樹狀陣列求凸點的操作了。
按a從小到大排序,相同b小的排前面,再相同c小的排前面。
然後倒著往二維樹狀數組裡加點(b,c),如果它右上角有比他大的點,則這個新三元組對答案沒貢獻。
注意long long。
程式碼:
#include<bits/stdc++.h> #define ll long long #define inf 0x3f3f3f3f3f3f3f3fLL using namespace std; const int maxn=1010; const int maxm=100010; ll C[maxn][maxn]; int n,m; int mp[maxm]; ll num[maxm]; struct node { int a,b,c; ll sum; node(){} node(int aa,int bb,int cc,ll dd) { a=aa;b=bb;c=cc;sum=dd; } bool operator<(node aa)const { if(aa.a!=a) return a<aa.a; else if(aa.b!=b) return b<aa.b; else return c<aa.c; } node operator +(const node &aa)const { return node(a,b,c,sum+aa.sum); } bool operator ==(const node &aa)const { return (!(*this<aa||aa<*this)); } }st[maxm]; int lb(int x){return x&(-x);} void add(int x,int y,ll v) { for(int i=x;i<maxn;i+=lb(i)) for(int j=y;j<maxn;j+=lb(j)) C[i][j]+=v; } ll query(int x,int y) { ll ans=0; for(int i=x;i>0;i-=lb(i)) for(int j=y;j>0;j-=lb(j)) { ans+=C[i][j]; } return ans; } int main() { int T,cas=1; scanf("%d",&T); int x,y; while(T--) { scanf("%d%d",&n,&m); memset(C,0,sizeof(C)); memset(mp,0,sizeof(mp)); memset(num,0,sizeof(num)); for(int i=0;i<n;i++) { scanf("%d%d",&x,&y); if(mp[y]<x) {mp[y]=x;num[y]=1;} else if(mp[y]==x){num[y]++;} } int cnt=0; for(int i=0;i<m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); if(mp[z]) st[cnt++]=node(mp[z],x,y,num[z]); } sort(st,st+cnt); int tot=0; for(int i=1;i<cnt;i++) { if(st[tot]==st[i]) st[tot]=st[tot]+st[i]; else st[++tot]=st[i]; } ll ans=0; for(int i=tot;i>=0;i--) { int x=st[i].b,y=st[i].c; ll f=query(1000,1000)-query(x-1,1000)-query(1000,y-1)+query(x-1,y-1); if(!f) ans+=st[i].sum; add(x,y,1); } printf("Case #%d: %lld\n",cas++,ans); } return 0; }