P2745 题解
ZHONGZIJIE0608 · · 题解
首先,对于窗口的插入删除,为了节省复杂度,我们用双向链表维护。(单向链表不好找插入位置)
“置顶”“置底”两种操作可以通过插入删除解决。
对于“查询”操作,显然是只有顶部到当前窗口的信息是有用的。考虑在当前窗口的大小内维护被覆盖的区域面积。
这里不使用扫描线。注意到窗口数
注意到横纵坐标在
每次枚举矩形的左端点维护信息即可。
输入时要过滤掉多余的字符。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=70;
int Hash(char x){
if(x>='A'&&x<='Z')return x-'A'+1;
if(x>='a'&&x<='z')return (x-'a'+1)+('Z'-'A'+1);
return (x-'0'+1)+('z'-'a'+1)+('Z'-'A'+1);
}
struct Matrix{int X1,X2,Y1,Y2,pre,nxt;}a[N];
void Delete(int x){
a[a[x].pre].nxt=a[x].nxt;
a[a[x].nxt].pre=a[x].pre;
}
void Insert(int pos,int x){
a[x].pre=pos;
a[x].nxt=a[pos].nxt;
a[a[pos].nxt].pre=x;
a[pos].nxt=x;
}
int bottom=N-1;
int x[N*2],cntx,y[N*2],cnty;
unordered_map<int,int>lsx,lsy;
bool vis[N*2][N*2];
signed main(){
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
a[bottom].pre=0;a[0].nxt=bottom;
int T;cin>>T;
char op;
while(cin>>op){
char _1,_2,_3,_4,_5,_6,ID;
if(op=='w'){
cin>>_1>>ID;
int id=Hash(ID);
Insert(0,id);
cin>>_2>>a[id].X1>>_3>>a[id].Y1>>_4>>a[id].X2>>_5>>a[id].Y2>>_6;
if(a[id].X1>a[id].X2)swap(a[id].X1,a[id].X2);
if(a[id].Y1>a[id].Y2)swap(a[id].Y1,a[id].Y2);
}
else{
cin>>_1>>ID>>_2;int id=Hash(ID);
if(op=='d')Delete(id);
if(op=='b')Delete(id),Insert(a[bottom].pre,id);
if(op=='t')Delete(id),Insert(0,id);
if(op=='s'){
lsx.clear();lsy.clear();cntx=cnty=0;
memset(vis,0,sizeof vis);
for(int i=a[0].nxt;i!=a[id].nxt;i=a[i].nxt){
x[++cntx]=a[i].X1,x[++cntx]=a[i].X2;
y[++cnty]=a[i].Y1,y[++cnty]=a[i].Y2;
}
sort(x+1,x+1+cntx);
sort(y+1,y+1+cnty);
cntx=unique(x+1,x+1+cntx)-x-1;
cnty=unique(y+1,y+1+cnty)-y-1;
for(int i=1;i<=cntx;++i)lsx[x[i]]=i;
for(int i=1;i<=cnty;++i)lsy[y[i]]=i;
for(int p=a[0].nxt;p!=id;p=a[p].nxt){
for(int i=lsx[a[p].X1];i<lsx[a[p].X2]/*i 是当前块的左边界*/;++i)
for(int j=lsy[a[p].Y1];j<lsy[a[p].Y2]/*i 是当前块的左边界*/;++j)
vis[i][j]=1;
}
int ans=0;
int p=id;
for(int i=lsx[a[p].X1];i<lsx[a[p].X2]/*i 是当前块的左边界*/;++i)
for(int j=lsy[a[p].Y1];j<lsy[a[p].Y2]/*i 是当前块的左边界*/;++j){
if(!vis[i][j])ans+=(x[i+1]-x[i])*(y[j+1]-y[j]);
}
ans*=100;
double S= (a[id].X2-a[id].X1)*(a[id].Y2-a[id].Y1);
cout<<fixed<<setprecision(3)<<(ans*1.0/S)<<'\n';
}
}
}
return 0;
}