1. 程式人生 > 其它 >CF1214G Feeling Good

CF1214G Feeling Good

一、題目

點此看題

二、解法

高維問題首先考慮拆分,本題其實是能拆開的。也就是每一行開一個 \(\tt bitset\),然後對於兩行我們找到位置上的 \(01\) 對和 \(10\) 對就可以組成答案。

再翻譯一下就是兩行 \(\tt bitset\) 都有 \(1\) 並且出現位置不包含,那麼每次修改一行我們考慮它和其它所有行的變化,那麼時間複雜度 \(O(n\cdot m\cdot q\cdot\frac{1}{w})\)

無法優化?注意到本題並不需要求出對數,而只需要找出一個,相當於判斷有沒有解。可以尋找性質使我們判斷的物件變少,注意到我們將所有行按 \(1\) 的個數排序之後,如果全域性有解,那麼相鄰兩行必定會產生解:

證明:直接反證法,如果相鄰兩行都無解,根據包含關係的傳遞性兩兩都應該無解,與全域性有解這個條件矛盾。

那麼搞一個 \(\tt set\),每次只需要判斷和前驅後繼的 \(\tt bitset\) 做一次即可,時間複雜度 \(O(\frac{nq}{w})\)

三、總結

當遇到存在性詢問而不是統計性詢問的時候需要注意,可能存在結論使得不需要判斷全部情況。

本題的邏輯是如果全域性存在答案,那麼...必定存在答案,我認為這個思路比...更可能得到答案更高階。

#include <cstdio>
#include <bitset>
#include <iostream>
#include <set>
using namespace std;
const int M = 2005;
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,k,cnt[M];set<pii> s,t;bitset<M> b[M];
int pd(int x,int y)
{
	return (b[x]&b[y])!=b[x];
}
void add(int x)
{
	s.insert(mp(cnt[x],x));
	auto i=s.lower_bound(mp(cnt[x],x)),j=i;i--;j++;
	if(cnt[i->se] && j!=s.end() && pd(i->se,j->se))
		t.erase(mp(i->se,j->se));
	if(cnt[i->se] && pd(i->se,x))
		t.insert(mp(i->se,x));
	if(cnt[x] && j!=s.end() && pd(x,j->se))
		t.insert(mp(x,j->se));
}
void del(int x)
{
	s.erase(mp(cnt[x],x));
	auto j=s.lower_bound(mp(cnt[x],x)),i=j;i--;
	if(cnt[i->se] && pd(i->se,x))
		t.erase(mp(i->se,x));
	if(cnt[x] && j!=s.end() && pd(x,j->se))
		t.erase(mp(x,j->se));
	if(cnt[i->se] && j!=s.end() && pd(i->se,j->se))
		t.insert(mp(i->se,j->se));
}
signed main()
{
	n=read();m=read();k=read();
	for(int i=0;i<=n;i++) s.insert(mp(0,i));
	for(int i=1;i<=k;i++)
	{
		int a=read(),l=read(),r=read();
		bitset<M> tmp;tmp.set();
		tmp>>=(M-(r-l+1));tmp<<=l;
		del(a);b[a]=b[a]^tmp;
		cnt[a]=b[a].count();add(a);
		if(t.empty()) puts("-1");
		else
		{
			int xl=t.begin()->fi,xr=t.begin()->se;
			bitset<M> tmp;tmp=b[xl]^b[xr];
			int yl=(tmp&b[xl])._Find_first();
			int yr=(tmp&b[xr])._Find_first();
			if(xl>xr) swap(xl,xr);
			if(yl>yr) swap(yl,yr);
			printf("%d %d %d %d\n",xl,yl,xr,yr);
		}
	}
}