CF1214G Feeling Good
阿新 • • 發佈:2021-11-04
一、題目
二、解法
高維問題首先考慮拆分,本題其實是能拆開的。也就是每一行開一個 \(\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); } } }