这个扫描线气死我了,我理解其中思想 却不知道怎么写
彻底被结构体优先队列搞疯,以前以为在结构体里面重载运算符就是优先队列结构体,发现错误的照样sort。
我去,这是真的难受 无奈之下写了一个pair套pair再套pair还套pair
这可是要exs我了,想define F->first 发现不行鬼畜的first 和second 然后 码长很长。
晕死了,然后蜜汁离散化 然后蜜汁 优先队列。
在计算代价的时候GG了发现错了。然后 0分。
发现是不会扫描线的缘故,恶补扫描线。
花费了我3h也不知道怎么写扫描线,为什么要离散 怎么搞向上延伸的最大距离。
不会。。。
针对这道题 题目大意是求各个矩形面积的并。
我想我 可以 看书。然后不太会。
学了至少3h 我也不知道为什么可能中间思考了一些关于线段树的细节的问题。
这道题考虑将其一块一块分解 求面积 首先我们只要 用|x||y|就能求出每一块矩形。
然后考虑怎么维护x或者y 让x单调 将y放入线段树中 因为y是一个小数所以 考虑离散
经过多年离散发现 并不是所有的离散都是那三行离散化。
求出线每次扫描到的地方即可。
//#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<iomanip> #include<cstring> #include<string> #include<cstdlib> #include<cmath> #include<algorithm> #include<cctype> #include<utility> #include<set> #include<bitset> #include<queue> #include<stack> #include<deque> #include<map> #include<vector> #include<ctime> #define INF 2147483646 #define l(x) s[x].l #define r(x) s[x].r #define c(x) s[x].cnt #define sum(x) s[x].len using namespace std; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline long long read() { long long x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void put(long long x) { x<0?putchar('-'),x=-x:0; long long num=0;char ch[50]; while(x)ch[++num]=x%10+'0',x/=10; num==0?putchar('0'):0; while(num)putchar(ch[num--]); putchar(' ');return; } const int MAXN=1000; int n,m,num; double real[MAXN];//r存y的真实值 v存y的离散值 struct wy { double x,y,z; int k; bool operator <(const wy &h)const { return x<h.x; } }a[MAXN]; map<double,int>v; struct wy1 { int l,r; int cnt; double len; }s[MAXN]; void build(int p,int l,int r) { l(p)=l;r(p)=r; sum(p)=0;c(p)=0; if(l==r)return; int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); } void change(int p,int l,int r,int d) { if(l<=l(p)&&r>=r(p))sum(p)=((c(p)+=d)?real[r(p)+1]-real[l(p)]:0); if(l(p)==r(p))return; int mid=(l(p)+r(p))>>1; if(l<=mid)change(p<<1,l,r,d); if(r>mid)change(p<<1|1,l,r,d); sum(p)=(c(p)?real[r(p)+1]-real[l(p)]:sum(p<<1)+sum(p<<1|1)); } int main() { //freopen("1.in","r",stdin); while(1) { n=read(); if(n==0)break; for(int i=1;i<=n;i++) { int k=i<<1; double y,z; scanf("%lf %lf %lf %lf",&a[k-1].x,&y,&a[k].x,&z); real[k-1]=a[k-1].y=a[k].y=y;//先搞一波y值 real[k]=a[k-1].z=a[k].z=z; a[k-1].k=1; a[k].k=-1; } n=n<<1; sort(real+1,real+1+n); m=unique(real+1,real+1+n)-(real+1);//离散 建一棵线段树 for(int i=1;i<=m;i++)v[real[i]]=i; sort(a+1,a+1+n);//按照x从小到大排序 double ans=0; build(1,1,m-1);//发现线段树存某个点的cnt没有任何意义 //应该存一段区间的值 那么我们建m-1个区间即可 for(int i=1;i<n;i++) { int y=v[a[i].y],z=v[a[i].z]-1; //cout<<y<<' '<<z<<endl; change(1,y,z,a[i].k); ans+=sum(1)*(a[i+1].x-a[i].x); //cout<<sum(1)<<endl; } printf("Test case #%d ",++num); printf("Total explored area: %.2lf ",ans); puts(""); } return 0; }
这道题就是我开头吐槽的那道困扰我好久的题目。很气。
学过扫描线了 然后发现这题并非是线段树 或者说线段树非常难写。
点开的题解中发现一篇非常简单体现了扫描线的思路(当然和我想的差不多喽)
差的是对STL multiset 的使用罢了。
这里使用multiset维护整个扫描线。然后一条一条加即可完成操作!
非常巧妙的思想!
//#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<iomanip> #include<cstring> #include<string> #include<cstdlib> #include<cmath> #include<algorithm> #include<cctype> #include<utility> #include<set> #include<bitset> #include<queue> #include<stack> #include<deque> #include<map> #include<vector> #include<ctime> #define INF 2147483646 #define h(p) t[p].h #define l(p) t[p].x #define k(p) t[p].k using namespace std; char buf[1<<15],*fs,*ft; inline char getc() { return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++; } inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void put(int x) { x<0?putchar('-'),x=-x:0; int num=0;char ch[50]; while(x)ch[++num]=x%10+'0',x/=10; num==0?putchar('0'):0; while(num)putchar(ch[num--]); putchar(' ');return; } const int MAXN=100002; int x[MAXN<<2],y[MAXN<<2]; int n,m,cnt; struct wy { int h,x,k; }t[MAXN<<1]; multiset<int>q; int cmp(wy x,wy y) { if(x.x!=y.x)return x.x<y.x; if(x.k!=y.k)return x.k<y.k; if(x.k==1)return x.h>y.h; return x.h<y.h; } int main() { //freopen("1.in","r",stdin); n=read(); for(int i=1;i<=n;i++) { int high,xx,yy; high=read();xx=read();yy=read(); ++m,l(m)=xx,h(m)=high,k(m)=1; ++m,l(m)=yy,h(m)=high,k(m)=2; } sort(t+1,t+1+m,cmp); q.insert(0); for(int i=1;i<=m;i++) { int mx=*q.rbegin(); if(k(i)==1) { if(h(i)>mx) { ++cnt;x[cnt]=l(i);y[cnt]=mx; ++cnt;x[cnt]=l(i);y[cnt]=h(i); q.insert(h(i)); } else q.insert(h(i)); } if(k(i)==2) { if(h(i)==mx&&q.count(mx)==1) { q.erase(mx); ++cnt;x[cnt]=l(i);y[cnt]=mx; ++cnt;x[cnt]=l(i);y[cnt]=*q.rbegin(); } else q.erase(q.find(h(i))); } } put(cnt);puts(""); for(int i=1;i<=cnt;i++)put(x[i]),put(y[i]),puts(""); return 0; }
既见君子,云胡不喜!