bzoj5328: [Sdoi2018]物理實驗

果真我仍是太菜了,爆了一天才過。。。。隔壁肉絲都不知道喊了多少句哎╮(╯▽╰)╭我又A了什麼傻逼題(然鵝就是wf和國集的題QWQ)ios

其實這個題就是個裸題,可是我就是不會。。。less

這個題第一步就是明顯的旋轉座標系(不會的百度),注意要先平移座標系再旋轉函數

而後問題就變成x軸上下有一些線段,考慮覆蓋長度爲L的一段區間,看看區間內最接近x軸的線段的長度和(也能夠直接按題意理解,好像更好懂)spa

線段是斜着的很難搞,可是假如覆蓋了l~r的區間,那麼也能夠經過三角函數搞出線段長度指針

能夠先弄一個相似離散化的東西,個人意思是每一個線段的左右端點的x座標爲斷點,相鄰x座標之間能夠當作一段(大概就是這樣不懂評論我)code

主要問題在處理出每一段最接近x軸的線段是那一條,假如搞定了這個東西,咱們能夠正反枚舉每一個段,而後能要段就要,再加上下一個段的一部分更新答案,這個雙指針掃一下就好blog

考慮按端點的x座標上掃描線,對於線段有一個關鍵的性質,就是線段不相交,這裏隱含着這麼一個東西:假如線段u的左端點的x座標較小,線段v的左端點在線段u的上方/下方,直到u被刪除線段的上下關係都是不變的,不然線段就相交了get

換句話說,不相交知足對於在任意一條線段的左右端點x座標框住的區間中,任意一條線段和這一條線段的上下關係不變string

那麼有這個東西就能夠作了,用set維護一下上方最下的線段和下方最上的線段便可it

#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<set>
using namespace std; typedef long double LD; const int _=1e2; const int maxn=1e4+_; const LD eps=1e-12; LD sqr(LD x){return x*x;} int n; struct point{LD x,y; point(){} point(LD X,LD Y){x=X,y=Y;}}; LD getdis(point p1,point p2){return sqrt(sqr(p1.x-p2.x)+sqr(p1.y-p2.y));} LD slope(point p1,point p2){return (p2.y-p1.y)/(p2.x-p1.x);} LD multi(point p1,point p2,point p0) { LD x1,y1,x2,y2; x1=p1.x-p0.x; y1=p1.y-p0.y; x2=p2.x-p0.x; y2=p2.y-p0.y; return x1*y2-x2*y1; } //------------------------------------------------def-----------------------------------------------------

struct board { point A,B; LD g;//長度變化的比值 1/cos
    void getg(){g=getdis(A,B)/fabs(A.x-B.x);} }b[maxn];bool cmp(board b1,board b2){return b1.A.y<b2.A.y;} bool bbbbcmp(board b1,board b2){return b1.A.x<b2.A.x;} LD co,si; point rot(point p){return point(p.x*co-p.y*si,p.y*co+p.x*si);} void rotate() { LD d=getdis(b[n+1].A,b[n+1].B); co=fabs(b[n+1].A.x-b[n+1].B.x)/d; si=fabs(b[n+1].A.y-b[n+1].B.y)/d; if(b[n+1].A.x<b[n+1].B.x&&b[n+1].A.y<b[n+1].B.y)si=-si; for(int i=1;i<=n;i++) { b[i].A.x-=b[n+1].A.x,b[i].A.y-=b[n+1].A.y; b[i].B.x-=b[n+1].A.x,b[i].B.y-=b[n+1].A.y; b[i].A=rot(b[i].A); b[i].B=rot(b[i].B); if(b[i].A.x>b[i].B.x)swap(b[i].A,b[i].B); b[i].getg(); // printf("%.10Lf %.10Lf %.10Lf %.10Lf\n",b[i].A.x,b[i].A.y,b[i].B.x,b[i].B.y);
 } } //---------------------------------------------------rotate-------------------------------------------------
 LD xx[2*maxn];int xlen; bool xx_cmp(LD x1,LD x2){return x1<x2;} int up[2*maxn],dp[2*maxn];//xx[i]~xx[i-1]這一段被那條線段覆蓋着 

struct seg { int id; seg(){} seg(int ID){id=ID;} friend bool operator <(seg s1,seg s2) { int x=s1.id,y=s2.id; if(x<y)return multi(b[x].B,b[y].A,b[x].A)>0; else   return multi(b[y].B,b[x].A,b[y].A)<0; } friend bool operator >(seg s1,seg s2) { int x=s1.id,y=s2.id; if(x<y)return multi(b[x].B,b[y].A,b[x].A)<0; else   return multi(b[y].B,b[x].A,b[y].A)>0; } };set< seg,less<seg> >us;set< seg,greater<seg> >ds; struct qq{int op,p;seg s; qq(){} qq(int OP,int P,seg S){op=OP,p=P,s=S;}}uq[2*maxn],dq[2*maxn];int uqlen,dqlen; bool qqqqcmp(qq q1,qq q2){return q1.p==q2.p?q1.op>q2.op:q1.p<q2.p;} int lb(LD d) { int l=1,r=xlen; while(l<=r) { int mid=(l+r)/2; if(fabs(xx[mid]-d)<=eps)return mid; if(xx[mid]>d)r=mid-1; else l=mid+1; } } void cover(int l1,int r1,int l2,int r2) { sort(b+l1,b+r1+1,bbbbcmp); sort(b+l2,b+r2+1,bbbbcmp); uqlen=dqlen=0; for(int i=l1;i<=r1;i++) { uq[++uqlen]=qq( 1,lb(b[i].A.x)+1,seg(i)); uq[++uqlen]=qq(-1,lb(b[i].B.x),seg(i)); } for(int i=l2;i<=r2;i++) { dq[++dqlen]=qq( 1,lb(b[i].A.x)+1,seg(i)); dq[++dqlen]=qq(-1,lb(b[i].B.x),seg(i)); } us.clear(),ds.clear(); sort(uq+1,uq+uqlen+1,qqqqcmp); sort(dq+1,dq+dqlen+1,qqqqcmp); int utp=1,dtp=1; for(int i=1;i<=xlen;i++) { while(utp<=uqlen&&uq[utp].p==i&&uq[utp].op==1)us.insert(uq[utp].s),utp++; while(dtp<=dqlen&&dq[dtp].p==i&&dq[dtp].op==1)ds.insert(dq[dtp].s),dtp++; if(!us.empty())up[i]=(*us.begin()).id; else up[i]=-1; if(!ds.empty())dp[i]=(*ds.begin()).id; else dp[i]=-1; while(utp<=uqlen&&uq[utp].p==i&&uq[utp].op==-1)us.erase(uq[utp].s),utp++; while(dtp<=dqlen&&dq[dtp].p==i&&dq[dtp].op==-1)ds.erase(dq[dtp].s),dtp++; } } //-----------------------------------------------cover------------------------------------------------------

int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n+1;i++) scanf("%Lf%Lf%Lf%Lf",&b[i].A.x,&b[i].A.y,&b[i].B.x,&b[i].B.y); scanf("%Lf",&b[n+1].g); if(b[n+1].A.x>b[n+1].B.x)swap(b[n+1].A,b[n+1].B); rotate(); //....step1.......
        
        int pp=n+1; sort(b+1,b+n+1,cmp); xlen=0; for(int i=1;i<=n;i++) { if(b[i].A.y>0&&pp==n+1)pp=i; xx[++xlen]=b[i].A.x; xx[++xlen]=b[i].B.x; } sort(xx+1,xx+xlen+1); int tp=1; for(int j=2;j<=xlen;j++) if(fabs(xx[j]-xx[tp])>eps)xx[++tp]=xx[j]; xlen=tp; cover(pp,n,1,pp-1); //....step2.......
 LD ans=0,sum=0; int j=1; for(int i=2;i<=xlen;i++) { while(j<xlen&&(xx[j+1]-xx[i-1])<=b[n+1].g) { j++; if(up[j]!=-1)sum+=(xx[j]-xx[j-1])*b[up[j]].g; if(dp[j]!=-1)sum+=(xx[j]-xx[j-1])*b[dp[j]].g; } LD num=0; if(j<xlen) { if(up[j+1]!=-1)num+=min(xx[j+1]-xx[j],b[n+1].g-(xx[j]-xx[i-1]))*b[up[j+1]].g; if(dp[j+1]!=-1)num+=min(xx[j+1]-xx[j],b[n+1].g-(xx[j]-xx[i-1]))*b[dp[j+1]].g; } ans=max(ans,sum+num); if(up[i]!=-1)sum-=(xx[i]-xx[i-1])*b[up[i]].g; if(dp[i]!=-1)sum-=(xx[i]-xx[i-1])*b[dp[i]].g; // printf("%.10Lf %.10Lf %.10Lf\n",xx[i]-xx[i-1],b[up[i]].g,b[dp[i]].g);
 } j=xlen;sum=0; for(int i=xlen;i>1;i--) { while(j>1&&(xx[i]-xx[j-1])<=b[n+1].g) { if(up[j]!=-1)sum+=(xx[j]-xx[j-1])*b[up[j]].g; if(dp[j]!=-1)sum+=(xx[j]-xx[j-1])*b[dp[j]].g; j--; } LD num=0; if(j>1) { if(up[j]!=-1)num+=min(xx[j]-xx[j-1],b[n+1].g-(xx[i]-xx[j]))*b[up[j]].g; if(dp[j]!=-1)num+=min(xx[j]-xx[j-1],b[n+1].g-(xx[i]-xx[j]))*b[dp[j]].g; } ans=max(ans,sum+num); if(up[i]!=-1)sum-=(xx[i]-xx[i-1])*b[up[i]].g; if(dp[i]!=-1)sum-=(xx[i]-xx[i-1])*b[dp[i]].g; } printf("%.10Lf\n",ans); // break; //....step3.......
 } return 0; }
相關文章
相關標籤/搜索