CF793G Oleg and chess 题解

\(\text{类似于主席树优化建图,直接放一张图片。}\)

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=3e4+5;
const int oo=5e6;
struct node{
	int nxt;int to;int flow;
}e[N*500];
int head[N*60],tot;
int cur[N*60],dep[N*60];
int id[N*4],tag[N*4];bool islf[N*4];int lid[N*4];
int n,m,S,T,idx;int xa,ya,xb,yb;
struct Mnode{
	int x;int y;int z;
	inline bool operator < (const Mnode &t)const{
		return (t.x^x?t.x<x:(t.y^y?t.y<y:t.z<z));
	}
};
struct Tp{
	int l;int r;int v;
}tmp;
vector<Tp> opt[N];
queue<int> Q;
inline void read(int &x) 
{
	int f=1;char c;
	for(x=0,c=getchar();c<'0'||c>'9';c=getchar()) if(c=='-') f=-1;
	for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48); x*=f;
} 
inline int mn(int _x,int _y){return _x<_y?_x:_y;}
inline int mx(int _x,int _y){return _x>_y?_x:_y;}
inline int ab(int _x){return _x<0?-_x:_x;}
inline void add(int from,int to,int flow){
	e[++tot].to=to;e[tot].flow=flow;
	e[tot].nxt=head[from];head[from]=tot;
}
inline void lnk(int from,int to,int flow){
	add(from,to,flow);add(to,from,0);return ;
}
inline void pushup(int x){
	if(tag[x]) return ;
	if(islf[x]){lnk(id[x],lid[x]+n,oo);return ;}
	else{
		if(!tag[x<<1])lnk(id[x],id[x<<1],oo);
		if(!tag[x<<1|1]) lnk(id[x],id[x<<1|1],oo);
	}
	return ;
}
inline void build(int x,int l,int r){
	id[x]=++idx;
	if(l==r){islf[x]=true;lid[x]=l;lnk(idx,lid[x]+n,oo);return ;}
	int mid=l+r>>1;
	build(x<<1,l,mid);build(x<<1|1,mid+1,r);
	pushup(x);return ;
}
inline void update(int x,int l,int r,int ql,int qr,int v){
	id[x]=++idx;
	if(ql<=l&&r<=qr){
		tag[x]+=v;pushup(x);return ;
	}
	int mid=l+r>>1;
	if(ql<=mid) update(x<<1,l,mid,ql,qr,v);
	if(qr>mid) update(x<<1|1,mid+1,r,ql,qr,v);
	pushup(x);return ;
}

inline bool bfs(int s,int t){
	for(int i=0;i<=idx;i++){
		cur[i]=head[i];dep[i]=-1;
	}
	while(!Q.empty()) Q.pop();
	dep[s]=0;Q.push(s);
	while(!Q.empty()){
		int tp=Q.front();Q.pop();
		for(int i=head[tp];i;i=e[i].nxt){
			int v=e[i].to;
			if(dep[v]==-1&&e[i].flow>0){
				dep[v]=dep[tp]+1;
				Q.push(v);
				if(v==t) return true;
			}
		}
	}
	if(dep[t]==-1) return false;
	else return true;
}
inline int dfs(int x,int flow,int t){
	if(x==t||flow<=0) return flow;
	int overflow=flow,tmp;
	for(int &i=cur[x];i;i=e[i].nxt){
		int v=e[i].to;
		if(dep[v]==dep[x]+1&&e[i].flow>0){
			tmp=dfs(v,mn(flow,e[i].flow),t);
			if(tmp<=0) dep[v]=-1;
			flow-=tmp;e[i].flow-=tmp;
			e[i^1].flow+=tmp;
			if(flow<=0) break;
		}
	}
	return overflow-flow;
}
inline int Dinic(int s,int t){
	int rest=0;
	while(bfs(s,t)) rest+=dfs(s,oo,t);
	return rest;
}
inline bool cmp(Tp p,Tp q){
	return p.v>q.v;
}
int main()
{
	read(n);read(m);
	S=0;T=2*n+1;idx=2*n+1;tot=1;
	for(int i=1;i<=n;i++) lnk(S,i,1);
	for(int i=1;i<=n;i++) lnk(i+n,T,1);
	build(1,1,n);
	for(int i=1;i<=m;i++){
		read(xa);read(ya);read(xb);read(yb);
		opt[ya].push_back((Tp){xa,xb,1});
		opt[yb+1].push_back((Tp){xa,xb,-1});
	}
	for(int i=1;i<=n;i++){
		sort(opt[i].begin(),opt[i].end(),cmp);
		for(int j=0;j<opt[i].size();j++){
			tmp=opt[i][j];
			update(1,1,n,tmp.l,tmp.r,tmp.v);
		}
		if(!tag[1]) lnk(i,id[1],1);
	}
	printf("%d\n",Dinic(S,T));
	return 0;
}  

posted @ 2023-02-11 13:24  剑落星河  阅读(37)  评论(0)    收藏  举报