Usaco Training Section 5.3 Window Area
阿新 • • 發佈:2018-11-12
有一堆窗戶,以及一些建立、置頂、置地、刪除的操作,中間要詢問幾次某個窗戶可見的百分比是多少。
對於建立、置頂、置地、刪除的操作,直接模擬即可。主要是詢問。
求可見百分比,要求出可見範圍,也就是求被覆蓋的面積,這是經典的矩陣覆蓋。可用掃描線來實現。
懶得寫線段樹(貌似也並不需要),直接排序+推一推。
#include<bits/stdc++.h> #define ll long long #define ull unsigned long long #define inf 2147483647 #define mp make_pair #define pii pair<int,int> #define pb push_back #define r1 rt<<1 #define r2 rt<<1|1 #define ld long double using namespace std; inline int read(){ int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } struct node{ int x1,y1,x2,y2; }b[200],a[200]; struct node2{ int l,r; }d[200]; vector<int> v; int c[200]; inline bool cmp(node2 x,node2 y){ if(x.l!=y.l) return x.l<y.l; else return x.r<y.r; } int main() { ios::sync_with_stdio(false); freopen("window.in","r",stdin); freopen("window.out","w",stdout); string s; while(cin>>s){ if(s[0]=='w'){ int i=s[2]; int p=4,y1=0,x1=0,x2=0,y2=0; while(s[p]!=',') x1=(x1<<1)+(x1<<3)+(s[p]^48),++p;++p; while(s[p]!=',') y1=(y1<<1)+(y1<<3)+(s[p]^48),++p;++p; while(s[p]!=',') x2=(x2<<1)+(x2<<3)+(s[p]^48),++p;++p; while(s[p]!=')') y2=(y2<<1)+(y2<<3)+(s[p]^48),++p; a[i].x1=min(x1,x2),a[i].y1=min(y1,y2),a[i].x2=max(x1,x2),a[i].y2=max(y1,y2); v.pb(i); } else if(s[0]=='t'){ int i=s[2],j; for(j=0;j<v.size();++j) if(v[j]==i) break; v.erase(v.begin()+j); v.pb(i); } else if(s[0]=='b'){ int i=s[2],j; for(j=0;j<v.size();++j) if(v[j]==i) break; v.erase(v.begin()+j); v.insert(v.begin(),i); } else if(s[0]=='d'){ int i=s[2],j; for(j=0;j<v.size();++j) if(v[j]==i) break; v.erase(v.begin()+j); } else{ int x=s[2],p; for(p=0;p<v.size();++p) if(v[p]==x) break; int tot=0,cnt=0; for(int i=p+1;i<v.size();++i){ b[++tot].x1=max(a[x].x1,a[v[i]].x1); b[tot].y1=max(a[x].y1,a[v[i]].y1); b[tot].x2=min(a[x].x2,a[v[i]].x2); b[tot].y2=min(a[x].y2,a[v[i]].y2); if(b[tot].x1>b[tot].x2||b[tot].y1>b[tot].y2) --tot; else c[++cnt]=b[tot].x1,c[++cnt]=b[tot].x2; } if(tot==0){ cout<<"100.000"<<endl; continue; } sort(c+1,c+cnt+1); int pos=1; ld ans=0; for(int i=1;i<cnt;++i){ int sum=0; for(int j=1;j<=tot;++j) if(b[j].x1<=c[i]&&c[i+1]<=b[j].x2)d[++sum].l=b[j].y1,d[sum].r=b[j].y2; sort(d+1,d+sum+1,cmp); ld le=0;int j; for(j=1;j<=sum;++j){ int st=d[j].l,en=d[j].r; while(j+1<=sum&&en>=d[j+1].l){ ++j; en=max(en,d[j].r); } le+=en-st; } ans+=le*(ld)(c[i+1]-c[i]); } ld area=(ld)(a[x].x2-a[x].x1)*(ld)(a[x].y2-a[x].y1); ld y=(area-ans)/area; y*=100; cout<<setiosflags(ios::fixed)<<setprecision(3)<<y<<endl; } } return 0; }