echarts圖形顯示&echarts圖形顏色不相容所有瀏覽器問題
阿新 • • 發佈:2021-06-20
掃描線
掃描線+離散化+線段樹
(以下引用自@kk303的部落格)
初始狀態:
掃到最下面的線,點更新為紅色部分:
掃到下一根線,求出綠色部分的面積,加入答案,更新計數器:
同上,求出黃色部分面積,加入答案:
同上,求出灰色部分面積,加入答案:
同上,求出紫色部分面積,加入答案:
同上,求出藍色部分面積,加入答案:
掃描到最後一條邊了,結束!
面積並
就是掃描線,純的
\(code\)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define maxn 200010//線段樹4倍空間!!! #define int long long using namespace std; template<typename T> inline void read(T &x){ x=0;bool flag=0;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') flag=1; for(;isdigit(c);c=getchar()) x=x*10+(c^48); if(flag) x=-x; } int n,x1,x2,y1,y2,ans; int cnt,X[maxn]; int t[2*maxn],tag[2*maxn],rt,ls[2*maxn],rs[2*maxn]; struct data{ int l; int r; int h; int k;//權值1/-1 }lin[maxn]; bool cmp(data x,data y){ if(x.h==y.h) return x.k>y.k;//******** return x.h<y.h; } void pushup(int x,int l,int r){ if(tag[x]) t[x]=X[r+1]-X[l]; else t[x]=t[ls[x]]+t[rs[x]]; } void update(int &x,int l,int r,int cl,int cr,int k){ if(!x) x=++cnt; if(cl<=l&&cr>=r){ tag[x]+=k; pushup(x,l,r); return ; } int mid=(l+r)/2; if(cl<=mid) update(ls[x],l,mid,cl,cr,k); if(cr>=mid+1) update(rs[x],mid+1,r,cl,cr,k); pushup(x,l,r); } signed main(){ read(n); for(int i=1;i<=n;i++){ read(x1),read(y1),read(x2),read(y2); X[i*2]=x1,X[i*2-1]=x2; lin[i*2]=(data){x1,x2,y1,1}; lin[i*2-1]=(data){x1,x2,y2,-1}; } sort(X+1,X+2*n+1); sort(lin+1,lin+2*n+1,cmp); int m=unique(X+1,X+2*n+1)-X-2;//去重 for(int i=1;i<=2*n;i++){ int l=lower_bound(X+1,X+m+1,lin[i].l)-X; int r=lower_bound(X+1,X+m+1,lin[i].r)-X-1; //-------------- // cout<<l<<" "<<r<<endl; // cout<<rt<<endl; // cout<<t[rt]<<endl; // cout<<lin[i].h-lin[i-1].h<<endl; // cout<<"*****"<<endl; ans+=t[rt]*(lin[i].h-lin[i-1].h); update(rt,1,m,l,r,lin[i].k); } cout<<ans<<endl; return 0; } /* 2 100 100 200 200 150 150 250 255 // 18000 */
也是板子,就不寫了
面積交
題目求的情況很好處理,覆蓋至少兩次的都可以,所以我們用 \(tag\) 來記錄該節點表示的區間完全被覆蓋。
\(tag \ge 2\) 表示該區間被完全覆蓋 \(\ge 2\) 次,這正是我們需要的。 \(tag=1\) 表示被完全覆蓋切覆蓋長度就是區間長度。 \(tag=0\) 表示沒被完全覆蓋,但是可能覆蓋一部分,所以要算出該區間中被覆蓋的長度。
由此我們可以算出被覆蓋一次和被覆蓋兩次的長度,我們用 \(one\) 和 \(two\) 來存。
為什麼這裡存的只是長度呢?因為由掃描線的原理可得,我們是隨著水平線的掃描來一塊一塊加入答案的,高度直接由相減可得,這裡就只記錄要加入的矩形的長度即可。
推廣一下,若求覆蓋3次,4次...也可以這樣搞,當然次數太多就不行了。
-
其實樣例大概是有誤差的,\(7.63->7.62\)
在這上面調一年 -
對於題目中的 注意:本題的輸入資料較多,推薦使用 \(scanf\) 讀入資料. ,其實 \(cin\) 也是可過的(親測
-
空間要開夠!
別問我怎麼知道的
\(code\)
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define maxn 4010//線段樹4倍空間!!! #define int long long using namespace std; template<typename T> inline void read(T &x){ x=0;bool flag=0;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') flag=1; for(;isdigit(c);c=getchar()) x=x*10+(c^48); if(flag) x=-x; } int t,n; int tag[2*maxn]; double x1,x2,y1,y2,ans; double X[maxn],one[2*maxn],two[2*maxn],ls[2*maxn],rs[2*maxn]; struct data{ double l; double r; double h; int k; }lin[2*maxn]; bool cmp(data x,data y){ if(x.h==y.h) return x.k>y.k; return x.h<y.h; } void pre(){ ans=0; memset(tag,0,sizeof(tag)); memset(one,0,sizeof(one)); memset(two,0,sizeof(two)); } void pushup(int x,int l,int r){ if(tag[x]>=2) two[x]=one[x]=X[r+1]-X[l]; if(tag[x]==1){ one[x]=X[r+1]-X[l]; if(l==r) two[x]=0; else two[x]=one[x*2]+one[x*2+1]; } if(tag[x]==0){ if(l==r) one[x]=two[x]=0; else{ one[x]=one[x*2]+one[x*2+1]; two[x]=two[x*2]+two[x*2+1]; } } } void update(int x,int l,int r,int cl,int cr,int k){ if(cl<=l&&cr>=r){ tag[x]+=k; pushup(x,l,r); return ; } int mid=(l+r)/2; if(cl<=mid) update(x*2,l,mid,cl,cr,k); if(cr>=mid+1) update(x*2+1,mid+1,r,cl,cr,k); pushup(x,l,r); } signed main(){ read(t); while(t--){ read(n); for(int i=1;i<=n;i++){ cin>>x1>>y1>>x2>>y2; X[i]=x1,X[i+n]=x2; lin[i]=(data){x1,x2,y1,1}; lin[i+n]=(data){x1,x2,y2,-1}; } sort(X+1,X+2*n+1); sort(lin+1,lin+2*n+1,cmp); pre(); int m=unique(X+1,X+2*n+1)-X-1; for(int i=1;i<=2*n-1;i++){ int l=lower_bound(X+1,X+m+1,lin[i].l)-X; int r=lower_bound(X+1,X+m+1,lin[i].r)-X; //-------------- // cout<<l<<" "<<r<<endl; // cout<<rt<<endl; // cout<<two[rt]<<endl; // cout<<lin[i].h-lin[i-1].h<<endl; // cout<<"*****"<<endl; if(l<r) update(1,1,m,l,r-1,lin[i].k); ans+=two[1]*(lin[i+1].h-lin[i].h); } printf("%.2lf\n",ans); } return 0; } /* 2 5 1 1 4 2 1 3 3 7 2 1.5 5 4.5 3.5 1.25 7.5 4 6 3 10 7 3 0 0 1 1 1 0 2 1 2 0 3 1 // 7.63 0.00 */ /* 1 5 1 3 5 7 2 3 15 20 2.13 5.64 3 8 1 5 4 6 6 3 10 7 // 29.87 */
周長並
在寫了,寫完更