【IOI2018】排座位
2021/6/26 23:30:21
本文主要是介绍【IOI2018】排座位,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
过来补常见套路题
对于前缀\([1,i]\)将它们染黑,考虑所有\((H+1) \times (W+1)\)个\(2 \times 2\)小正方形,可以证明\([1,i]\)形成矩形充要条件是:
- 恰好\(4\)个有一个黑格的\(2 \times 2\)小正方形
- 没有任何一个有三个黑格的\(2 \times 2\)小正方形
同时可以发现有一个或三个黑格的小正方形总数不小于\(4\)
于是线段树维护所有前缀的有一个或三个黑格的小正方形个数,维护最小值及其个数。
初始化的时候可以线性建树。
时间复杂度\(O(HW+32Q\log HW)\)是常数非常大的做法,也许可以压一压,不会了。。
#include "seats.h" #include<bits/stdc++.h> using namespace std; #define fp(i,l,r) for(register int (i)=(l);(i)<=(r);++(i)) #define fd(i,l,r) for(register int (i)=(l);(i)>=(r);--(i)) #define fe(i,u) for(register int (i)=front[(u)];(i);(i)=e[(i)].next) #define mem(a) memset((a),0,sizeof (a)) #define O(x) cerr<<#x<<':'<<x<<endl const int MAXN=1e6+10; struct node{ int mn,v; inline node operator+(const node &b)const{ if(mn==b.mn)return {mn,v+b.v}; return mn<b.mn?(*this):b; } }tr[MAXN<<2]; vector<int>mp[MAXN]; int H,W,n,R[MAXN],C[MAXN],tag[MAXN<<2]; #define lson o<<1 #define rson o<<1|1 inline void madd(int o,int v){ tr[o].mn+=v;tag[o]+=v; } inline void pushdown(int o){ if(!tag[o])return; madd(lson,tag[o]);madd(rson,tag[o]);tag[o]=0; } void add(int o,int l,int r,int ql,int qr,int v){ if(l>=ql&&r<=qr){madd(o,v);return;} int mid=l+r>>1;pushdown(o); if(ql<=mid)add(lson,l,mid,ql,qr,v); if(qr>mid)add(rson,mid+1,r,ql,qr,v); tr[o]=tr[lson]+tr[rson]; } inline void mdy(int x1,int x2,int x3,int x4,int coe){ int a[5]={0,x1,x2,x3,x4}; sort(a+1,a+5); if(a[1]<a[2])add(1,1,n,a[1],a[2]-1,coe); if(a[3]<a[4])add(1,1,n,a[3],a[4]-1,coe); } int sum[MAXN]; inline void mdy2(int x1,int x2,int x3,int x4){ int a[5]={0,x1,x2,x3,x4}; sort(a+1,a+5); if(a[1]<a[2])++sum[a[1]],--sum[a[2]]; if(a[3]<a[4])++sum[a[3]],--sum[a[4]]; } void build(int o,int l,int r){ if(l==r){tr[o]={sum[l],1};return;} int mid=l+r>>1; build(lson,l,mid);build(rson,mid+1,r); tr[o]=tr[lson]+tr[rson]; } void give_initial_chart(int HH,int WW,vector<int>RR,vector<int>CC){ H=HH;W=WW;n=H*W; fp(i,1,n)R[i]=RR[i-1]+1,C[i]=CC[i-1]+1; fp(i,0,H+1)mp[i].resize(W+2,n+1); fp(i,1,n)mp[R[i]][C[i]]=i; fp(i,1,H+1)fp(j,1,W+1)mdy2(mp[i-1][j-1],mp[i-1][j],mp[i][j-1],mp[i][j]); fp(i,1,n)sum[i]+=sum[i-1]; build(1,1,n); } inline void mdy(int x,int y,int coe){ mdy(mp[x][y],mp[x-1][y],mp[x][y-1],mp[x-1][y-1],coe); mdy(mp[x][y],mp[x-1][y],mp[x-1][y+1],mp[x][y+1],coe); mdy(mp[x][y],mp[x][y-1],mp[x+1][y-1],mp[x+1][y],coe); mdy(mp[x][y],mp[x][y+1],mp[x+1][y],mp[x+1][y+1],coe); } int swap_seats(int a,int b){ ++a;++b; mdy(R[a],C[a],-1);mdy(R[b],C[b],-1); swap(R[a],R[b]);swap(C[a],C[b]); mp[R[a]][C[a]]=a;mp[R[b]][C[b]]=b; mdy(R[a],C[a],1);mdy(R[b],C[b],1); return tr[1].mn==4?tr[1].v:0; }
这篇关于【IOI2018】排座位的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南