zoukankan      html  css  js  c++  java
  • Solution -「营业」「CF 527C」Glass Carving

    Description

    Link.

    有一个块 (n imes m) 的矩形,有 (q) 次操作,每次把矩形横 / 竖着切一刀,问切完后的最大矩形面积。

    Solution

    一个不同于大多数人、总时间复杂度 (mathcal{O}(nlog_{2}n)),每次回答 (mathcal{O}(alpha(n))) 的做法,瓶颈在排序。

    显然答案是最大行列相乘。首先我们把询问离线,然后逆序处理。你发现这相当于把切开变成了合并,最大值不降,于是可以直接维护。

    具体来说就是维护两个并查集,分别是行和列,然后再维护集合内元素个数,然后就直接合并。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline ll read() {
    	ll x=0,f=0;
    	char ch=getchar();
    	while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    	while(ch>='0'&&ch<='9') x=x*10+(ch&15),ch=getchar();
    	return f?-x:x;
    }
    const int N=200100;
    signed main() {
    	int m=read(),n=read(),q=read();
    	static int far[N],fac[N],szr[N],szc[N];
    	iota(far+1,far+m+1,1);
    	iota(fac+1,fac+n+1,1);
    	for(int i=1;i<=m;++i) szr[i]=1;
    	for(int i=1;i<=n;++i) szc[i]=1;
    	auto findr=[&](int x) {while(x!=far[x]) x=far[x]=far[far[x]]; return x;};
    	auto findc=[&](int x) {while(x!=fac[x]) x=fac[x]=fac[fac[x]]; return x;};
    	auto merger=[&](int x,int y) {x=findr(x),y=findr(y); (x!=y)&&(szr[y]+=szr[x],szr[x]=0,far[x]=y);};
    	auto mergec=[&](int x,int y) {x=findc(x),y=findc(y); (x!=y)&&(szc[y]+=szc[x],szc[x]=0,fac[x]=y);};
    	static int op[N],X[N];
    	vector<int> hx,vx;
    	for(int i=1; i<=q; ++i) {
    		char Op[4];
    		scanf("%s",Op);
    		op[i]=Op[0]=='H';
    		X[i]=read();
    		(op[i])&&(X[i]=n-X[i]);
    		(op[i])&&(hx.push_back(X[i]),1);
    		(!op[i])&&(vx.push_back(X[i]),1);
    	}
    	sort(hx.begin(),hx.end());
    	sort(vx.begin(),vx.end());
    	hx.insert(hx.begin(),0);
    	vx.insert(vx.begin(),0);
    	hx.push_back(n);
    	vx.push_back(m);
    	for(unsigned int i=1; i<hx.size(); ++i)
    		for(int j=hx[i-1]+2; j<=hx[i]; ++j) mergec(j-1,j);
    	for(unsigned int i=1; i<vx.size(); ++i)
    		for(int j=vx[i-1]+2; j<=vx[i]; ++j) merger(j-1,j);
    	ll mxr=0,mxc=0;
    	for(int i=1; i<=m; ++i) mxr=max(mxr,(ll)szr[findr(i)]);
    	for(int i=1; i<=n; ++i) mxc=max(mxc,(ll)szc[findc(i)]);
    	vector<ll> ans;
    	ans.push_back(mxr*mxc);
    	for(int i=q; i>1; --i) {
    		if(op[i]) mergec(X[i]+1,X[i]),mxc=max(mxc,(ll)szc[findc(X[i])]);
    		else merger(X[i],X[i]+1),mxr=max(mxr,(ll)szr[findr(X[i])]);
    		ans.push_back(mxr*mxc);
    	}
    	reverse(ans.begin(),ans.end());
    	for(ll x:ans) printf("%lld
    ",x);
    	return 0;
    }
    
  • 相关阅读:
    jQuery学习总结之基础知识持续更新中
    经典人生感悟 看看你少了那一条
    [SQL]清空数据方法大比拼
    2010年的最后一天
    javascript学习之闭包
    实现checkbox的全选/全不选/点选/行内点选(原生JS版和jQ版)
    挖掘经典:几乎被人遗忘的HTML七种用法 (转)
    下拉及多及弹出式菜单
    win7下注册一个com失败,权限不够
    Visual Studio 2010 自述文件
  • 原文地址:https://www.cnblogs.com/orchid-any/p/14987758.html
Copyright © 2011-2022 走看看