Usaco Training Section 5.5 Picture
阿新 • • 發佈:2019-02-01
求許多矩形的周長並。可以聯想到5.3的Window Area,這道題是求面積並,我們可以用掃描線+排序推一推/線段樹。
這道題我們同樣可以用掃描線來解決。
我的程式碼:
#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; } const int N=10005,M=30000; struct node{ int x1,x2,y,k; bool operator < (const node &b) const{ if(y!=b.y) return y<b.y; else return k>b.k; } }a[N]; struct seg{ int l,r,len,num,sum,lc,rc; }st[M<<2]; inline void pushup(int rt){ if(st[rt].sum>0){ st[rt].len=st[rt].r-st[rt].l+1; st[rt].lc=st[rt].rc=1; st[rt].num=1; } else if(st[rt].l==st[rt].r){ st[rt].len=st[rt].num=st[rt].lc=st[rt].rc=0; } else{ st[rt].len=st[r1].len+st[r2].len; st[rt].lc=st[r1].lc;st[rt].rc=st[r2].rc; st[rt].num=st[r1].num+st[r2].num-(st[r1].rc&st[r2].lc); } } inline void build(int l,int r,int rt){ st[rt].l=l;st[rt].r=r;st[rt].len=st[rt].num=st[rt].sum=st[rt].lc=st[rt].rc=0; if(l==r) return; int m=(l+r)>>1; build(l,m,r1); build(m+1,r,r2); } inline void update(int l,int r,int c,int rt){ if(st[rt].l>r||l>st[rt].r) return; if(l<=st[rt].l&&st[rt].r<=r){ st[rt].sum+=c; pushup(rt); return; } update(l,r,c,r1); update(l,r,c,r2); pushup(rt); } int main() { freopen("picture.in","r",stdin); freopen("picture.out","w",stdout); int n=read(),m=0,mx=-inf,mn=inf; for(int i=1;i<=n;++i){ int x1=read(),y1=read(),x2=read(),y2=read(); mx=max(mx,max(x1,x2)); mn=min(mn,min(x1,x2)); a[++m].x1=x1,a[m].x2=x2,a[m].y=y1,a[m].k=1; a[++m].x1=x1,a[m].x2=x2,a[m].y=y2,a[m].k=-1; } sort(a+1,a+m+1); build(mn,mx-1,1); int ans=0,last=0; for(int i=1;i<=m;++i){ update(a[i].x1,a[i].x2-1,a[i].k,1); //橫線 ans+=abs(st[1].len-last); //豎線 ans+=(a[i+1].y-a[i].y)*2*st[1].num; last=st[1].len; } printf("%d\n",ans); return 0; }
其實這題可以暴力,排個序推一推。
將橫邊和縱邊分開算,具體直接看程式碼就行了,很好理解。
#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,x2,y,k; bool operator < (const node &b) const{ if(y!=b.y) return y<b.y; else return k>b.k; } }a[20005]; struct nod{ int x1,x2,y1,y2; }b[20005]; int ans,n,m,f[2][20005]; inline void work(){ sort(a+1,a+m+1); memset(f,0,sizeof(f)); int x=1; while(x<=m){ int y=a[x].y; for(int i=1;i<=20000;++i) f[0][i]=f[1][i]; while(x<=m&&a[x].y==y){ for(int i=a[x].x1+10000;i<a[x].x2+10000;++i) f[1][i]+=a[x].k; ++x; } for(int i=1;i<=20000;++i){ if(f[0][i]==0&&f[1][i]>0) ++ans; if(f[1][i]==0&&f[0][i]>0) ++ans; } } } int main() { freopen("picture.in","r",stdin); freopen("picture.out","w",stdout); n=read();m=0; for(int i=1;i<=n;++i){ int x1=read(),y1=read(),x2=read(),y2=read(); a[++m].x1=x1,a[m].x2=x2,a[m].y=y1,a[m].k=1; a[++m].x1=x1,a[m].x2=x2,a[m].y=y2,a[m].k=-1; b[i].x1=x1,b[i].y1=y1,b[i].x2=x2,b[i].y2=y2; } work(); m=0; for(int i=1;i<=n;++i){ a[++m].x1=b[i].y1,a[m].x2=b[i].y2,a[m].y=b[i].x1,a[m].k=1; a[++m].x1=b[i].y1,a[m].x2=b[i].y2,a[m].y=b[i].x2,a[m].k=-1; } work(); printf("%d\n",ans); return 0; }
吐槽一下:這題在HDU上也有,但有個坑人的地方,在HDU上這題有多組資料,要修改一下。因為這個wa了好幾次啊!!!