UESTC 1525 Fruit Ninja(掃描線)

來源:互聯網
上載者:User

題意:有T組測試資料,每組資料的N,H,W表示有N個炸彈或水果,H和W表示用來“切”水果的板磚的長寬,要求W必須平行於X軸,H必須平行於Y軸。問一板磚下去,最多能拍到多少個水果(要求不能拍到炸彈),在拍到最多水果的前提下,問板磚有多少種拍水果的方案(即如果板磚的四條邊上都要水果“犧牲”,那麼方案數計一,否則板磚就可移動,那麼方案數就是so many!)

        下面的N行,每行給出炸彈或水果的座標,L X Y,如果L是'G'表示水果,如果是'B'表示炸彈,X和Y是座標。1<=N<=50000, 1<=X,Y,H,W<=25000。

        掃描線,方法類似於star in my window。不同的是我們把y的座標乘以2,這樣線段就是(x,y*2,(y+h)*2),(x+w,y*2,(y+h)*2)。這樣,如果是下標為奇數的點到達最大值,我們知道方案數一定是so many,這是y軸方向的限制——即與y平行的兩條邊上都有水果,怎麼處理x方向上的限制呢?我們把在依次遍曆每條邊的時候,一次只處理x座標相同的幾條邊(在排序的時候,我們優先入邊(加水果的邊)再出邊(減水果的邊),因為邊框上的水果是計入的),先處理入邊,這時候,可能更新最大值,後處理出邊時,如果這時最大值不變,那麼說明方案數也有so
many。

        最後線段樹的節點裡記錄拍到的水果的最大值和對應的方案樹。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define MID(a,b) (a+((b-a)>>1))#define INF (1LL<<30)const int N=100000;typedef long long LL;struct Segtree{struct Seg{int lft,rht;LL mx,cov,delay;int mid(){ return MID(lft,rht); }void init(){ mx=delay=0; cov=INF; }void fun(LL tmp) { mx+=tmp; delay+=tmp; }}tree[N*4];void PushDown(int ind){if(tree[ind].delay){tree[LL(ind)].fun(tree[ind].delay);tree[RR(ind)].fun(tree[ind].delay);tree[ind].delay=0;}}void PushUp(int ind){tree[ind].mx=max(tree[LL(ind)].mx,tree[RR(ind)].mx);tree[ind].cov=0;if(tree[ind].mx==tree[LL(ind)].mx)tree[ind].cov+=tree[LL(ind)].cov;if(tree[ind].mx==tree[RR(ind)].mx)tree[ind].cov+=tree[RR(ind)].cov;}void build(int lft,int rht,int ind){tree[ind].lft=lft;tree[ind].rht=rht;tree[ind].init();if(lft==rht){if( (lft&1) ==0 ) tree[ind].cov=1;}else{int mid=tree[ind].mid();build(lft,mid,LL(ind));build(mid+1,rht,RR(ind));}}void updata(int st,int ed,int ind,int valu){int lft=tree[ind].lft,rht=tree[ind].rht;if(st<=lft&&rht<=ed) tree[ind].fun(valu);else{PushDown(ind);int mid=tree[ind].mid();if(st<=mid) updata(st,ed,LL(ind),valu);if(ed> mid) updata(st,ed,RR(ind),valu);PushUp(ind);}}}seg;struct Line{int x,y1,y2,st,v;Line(){}Line(int x,int y1,int y2,int st,int v) :x(x),y1(y1),y2(y2),st(st),v(v) {}bool operator<(const Line &b)const{return x<b.x||(x==b.x&&st>b.st);}}line[N*4];int main(){int t;scanf("%d",&t);while(t--){int n,h,w,nl=0,mi=INF,mx=-INF;scanf("%d%d%d",&n,&h,&w);for(int i=0;i<n;i++){char op[5]; int x,y,y1,y2;scanf("%s%d%d",op,&x,&y);y1=y*2;y2=(y+h)*2;mi=min(mi,y1); mx=max(mx,y2);if(op[0]=='G'){line[nl++]=Line(x,y1,y2,1,1);line[nl++]=Line(x+w,y1,y2,-1,-1);}else{line[nl++]=Line(x,y1,y2,1,-INF);line[nl++]=Line(x+w,y1,y2,-1,INF);}}sort(line,line+nl);seg.build(mi,mx,1);LL ans=0,cnt=0;for(int i=0;i<nl;){int last=line[i].x;while(i<nl&&line[i].x==last&&line[i].st==1){seg.updata(line[i].y1,line[i].y2,1,line[i].v);i++;}if(ans==seg.tree[1].mx) cnt+=seg.tree[1].cov;else if(ans<seg.tree[1].mx){ans=seg.tree[1].mx;cnt=seg.tree[1].cov;}while(i<nl&&line[i].x==last&&line[i].st==-1){seg.updata(line[i].y1,line[i].y2,1,line[i].v);i++;}if(ans<=seg.tree[1].mx){ans=seg.tree[1].mx;cnt=INF;}}if(cnt>=INF) puts("so many!");else printf("%lld\n",cnt);printf("%lld\n\n",ans);}return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.