zoukankan      html  css  js  c++  java
  • 【IOI2018】排座位

    过来补常见套路题

    对于前缀([1,i])将它们染黑,考虑所有((H+1) imes (W+1))(2 imes 2)小正方形,可以证明([1,i])形成矩形充要条件是:

    1. 恰好(4)个有一个黑格的(2 imes 2)小正方形
    2. 没有任何一个有三个黑格的(2 imes 2)小正方形

    同时可以对于任意非空图形发现有一个黑格的小正方形总数不小于(4)

    于是线段树维护所有前缀的有一个或三个黑格的小正方形个数,维护最小值及其个数。

    初始化的时候可以线性建树。

    时间复杂度(O(HW+32Qlog 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;
    }
    
  • 相关阅读:
    BZOJ 2038: [2009国家集训队]小Z的袜子 (莫队)
    codevs 3981 动态最大子段和(线段树)
    ACM北大暑期课培训第八天
    ACM北大暑期课培训第七天
    ACM北大暑期课培训第六天
    ACM北大暑期课培训第五天
    ACM北大暑期课培训第四天
    HDU4403-模拟、数学
    HDU4296-ChengduOnling-贪心
    POJ3176-基础DP
  • 原文地址:https://www.cnblogs.com/WinterSpell/p/14939378.html
Copyright © 2011-2022 走看看