CF1214G Feeling Good 题解
题目链接
题目解法
我真菜啊,感觉每一步都不难,但一步都没想到/yun
考虑两行 \(x,y\) 什么时候可以构造出合法的矩形?
即 \(x\) 中需要有 \(y\) 对应位置为 \(0\) 的 \(1\),\(y\) 中需要有 \(x\) 对应位置为 \(0\) 的 \(1\)
归纳一下,\(x\) 不是 \(y\) 的子集 且 \(y\) 不是 \(x\) 的子集
我先想的是:是否只需要考虑相邻两行,但这显然是错的
事实上,只要拓展一下,把行按照行内 \(1\) 的个数排序,我们只需要考虑排序之后的相邻两行即可,证明也是显然的
我们用 \(bitset\) 维护一行的信息,\(set\) 维护排序之后的序列 就做完了
时间复杂度 \(O(nq\log n+\frac{n^2q}{64})\)
#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define all(x) x.begin(),x.end()
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
template<typename T> void read(T &FF){
FF=0;int RR=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
FF*=RR;
}
const int N=2010;
int n,m,q;
bitset<N> bs[N],dif,tmp;
set<pii> S;
set<pii> mat;
#define fi first
#define se second
bool chk(int a,int b){
dif=bs[a]^bs[b];
return (bs[a]&dif).any()&&(bs[b]&dif).any();
}
void del(int a){
auto it=S.find({bs[a].count(),a});
int prv=-1,nxt=-1;
if(it!=S.begin()) prv=(*prev(it)).se;
if(next(it)!=S.end()) nxt=(*next(it)).se;
if(prv!=-1&&mat.find({prv,a})!=mat.end()) mat.erase({prv,a});
if(nxt!=-1&&mat.find({a,nxt})!=mat.end()) mat.erase({a,nxt});
if(prv!=-1&&nxt!=-1&&chk(prv,nxt)) mat.insert({prv,nxt});
S.erase(it);
}
void ins(int a){
auto it=S.insert({bs[a].count(),a}).first;
int prv=-1,nxt=-1;
if(it!=S.begin()) prv=(*prev(it)).se;
if(next(it)!=S.end()) nxt=(*next(it)).se;
if(prv!=-1&&nxt!=-1&&mat.find({prv,nxt})!=mat.end()) mat.erase({prv,nxt});
if(prv!=-1&&chk(prv,a)) mat.insert({prv,a});
if(nxt!=-1&&chk(a,nxt)) mat.insert({a,nxt});
}
int main(){
read(n),read(m),read(q);
F(i,1,n) S.insert({0,i});
F(i,1,q){
int a,x,y;read(a),read(x),read(y);
del(a);
tmp.set();tmp>>=N-(y-x+1),tmp<<=x;
bs[a]^=tmp;
ins(a);
if(!mat.empty()){
auto [a,b]=*mat.begin();
if(a>b) swap(a,b);
dif=bs[a]^bs[b];
int ans1=(bs[a]&dif)._Find_first(),ans2=(bs[b]&dif)._Find_first();
if(ans1>ans2) swap(ans1,ans2);
printf("%d %d %d %d\n",a,ans1,b,ans2);
}
else puts("-1");
}
return 0;
}

浙公网安备 33010602011771号