由於存在相對顏色大小關係,我們考慮線段樹合併來維護這個結構。
為了後續的討論的方便,我們將lv
進行離散化。
這裡的離散化是在對統計不產生影響時,將所有的值都變得不同。
對於每個連通塊我們維護四顆線段樹分別表示表示:
同時維護兩個是為了之後處理直行道路時好處理。
初始化時,我們將每個點的相鄰的有互信道路
且沒有點的直接merge
起來,對於旁邊有鄰居的點,我們就在對應線段樹上的該點對應的值設為1
。
對於所有直行道路,我們預處理出每個點像上下左右最遠能走到**,以及是否是因為乙個放上棋子的點而停止,若是以乙個放上棋子的點而停止,那麼額外記錄一下這個點的位置。
注意:這裡的處理點是從前向後不斷加入的。
回答問題部分,我們先刪去這個點的貢獻:
對四周由互信道路
連起來的連通塊的該點對應lv
的貢獻置為0
。
對該點所在連通塊該位置的值設為1
。
對旁邊沒有放棋子的點merge
起來。
然後再回答詢問,答案分為個部分:
設當前詢問點為 \(u\) 。
+
所有在 \(u\) 聯通塊的空格
的個數。
+
所有與 \(u\) 聯通塊相鄰的可以被吃掉的棋子
的個數。
+
行和列的空格
貢獻的個數。
-
行和列的空格
中在互信道路中記錄的個數。
+
這上面,我們在1
中對 \(u\) 算了一次,在3,4
中分別減了 \(u\) 一次,所以答案還要+1
。
+
對於普信道路,我們判斷他是否是棋子
+
對於因為是乙個棋子擺在直行道路的最後而結束的直行道路,我們要判斷判斷它是否和 \(u\) 所在連通塊中互信道路
的空格相鄰。
然後就沒了。
細心一點,一點一點討論,寫出這道題的正解的思路還是很清晰的。
複雜度 \(o(n\log n)\) 。
**:
#include#define for(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
#define sz(x) (int)(x.size())
#define ll long long
#define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?eof:*p1++)
using namespace std;
char buf[100000],*p1=buf,*p2=buf;
inline int gi()
while(ch>='0'&&ch<='9')
return (f==1)?x:-x;
}const int maxn=2e5+5;
const int dr[4]=;
const int dc[4]=;
char tmp[maxn];
int n,m,q;
vector>s,t;
int col[maxn],lv[maxn],x[maxn],y[maxn];
int id[maxn],fa[maxn],ans[maxn];
//vectornodes_row[maxn],nodes_column[maxn];///空格
vector>neighbors[maxn];
vectornvis;
vectorlef[maxn],rig[maxn],up[maxn],down[maxn];
///up and down 是對應線段樹的column
///lef and rig 對應的是線段樹的row
///注意先merge在查詢,查詢時注意這個點要剪掉1
setnowr[maxn],nowc[maxn];
pairqcol[maxn],qrow[maxn];
vectorspecial[maxn];
vector>vis,ncol;
///vis,nvis->leval
struct segmentree///線段樹合併
inline void pushup(int u)
inline void update(int &u,int l,int r,int x,int v)
inline int query(int u,int l,int r,int x,int y)
inline int merge(int u,int v,int l,int r)
///直接合併,如果有點=1
}tree[2],row,column;
///分別按行列去統計該連通塊的點在直行道路的情況
inline int index_row(int x,int y)
inline int index_column(int x,int y)
inline int get(int x)
inline void init()
inline void merge(int u,int v)
inline void read(char *s)
inline void input()
for(i,1,n-1)
for(i,1,q)
); }
sort(ord.begin(),ord.end());
for(i,0,sz(ord)-1)
vis.resize(n+1),ncol.resize(n+1);
for(i,0,n)vis[i].resize(m+1),ncol[i].resize(m+1);
for(i,1,q)vis[x[i]][y[i]]=lv[i],ncol[x[i]][y[i]]=col[i];
for(i,1,n)for(j,1,m)
); int c=ncol[tx][ty];
if(vis[tx][ty]&&typ==3)tree[c].update(tree[c].rt[u],1,n*m,vis[tx][ty],1);
} column.update(column.rt[u],1,n*m,index_column(i,j),1);
row.update(row.rt[u],1,n*m,index_row(i,j),1);
int c=ncol[i][j],v=vis[i][j];
if(v)tree[c].update(tree[c].rt[u],1,n*m,v,1);
if(v)nvis[u]=v;
} for(i,1,n*m)fa[i]=i;
// for(i,1,n)for(j,1,m)
// for(i,1,n*m) }
}inline void solve()
for(j,1,m)
///特判普信道路以及直行道路的盡頭的顏色
for(i,1,q)
; qcol[i]=;
auto it=nowr[x[i]].lower_bound(y[i]);
if(it!=nowr[x[i]].end()&&(*it)<=rig[x[i]][y[i]])
if(it!=nowr[x[i]].begin()&&*(--it)>=lef[x[i]][y[i]])
it=nowc[y[i]].lower_bound(x[i]);
if(it!=nowc[y[i]].end()&&(*it)<=down[x[i]][y[i]])
if(it!=nowc[y[i]].begin()&&*(--it)>=up[x[i]][y[i]])
nowr[x[i]].insert(y[i]);
nowc[y[i]].insert(x[i]);
} for(int i=q;i>=1;--i)
nvis[u]=0;
// for(auto x:neighbors[u])
//
u=get(u);
tree[col[i]].update(tree[col[i]].rt[u],1,n*m,lv[i],0);
ans[i]=tree[col[i]^1].query(tree[col[i]^1].rt[u],1,n*m,1,lv[i]);
ans[i]+=column.sum[column.rt[u]];
///注意這裡column和row的情況沒處理完
ans[i]+=qcol[i].second-qcol[i].first;
ans[i]+=qrow[i].second-qrow[i].first;
ans[i]-=column.query(column.rt[u],1,n*m,qcol[i].first,qcol[i].second);
ans[i]-=row.query(row.rt[u],1,n*m,qrow[i].first,qrow[i].second);
ans[i]++;
int v=index_row(x[i],y[i]);
for(int x:special[v])
}for(auto x:neighbors[v])
}else
}} for(i,1,q)printf("%d\n",ans[i]);
} int main()
return 0;
}
比賽題解 NOIP2021 題解
可以先把十進位制表示下數字含有 7 的所有數都求出來,然後去列舉這些數的倍數,將其標記。如果當前列舉到的數被標記過了則就不需要再列舉倍數了 因為列舉的倍數肯定也被標記過了 時間複雜度 mathcal n log log n include include include using namespac...
NOIP2021 簡要覆盤 題解
luogu7961.設 f i,j,k,l 表示考慮前 i 位,放了 j 個數,字尾 k 個 1 狀壓 i 及前三位結果為 l 的權值和 無序 轉移平凡,最後分配順序即可。luogu7962.有經驗的選手很快發現等價於交換差分陣列,並不難發現差分陣列一定是單谷的,證明不會,但想一下方差反應的是 資料...
遊記 NOIP2021 遊記
遊 nm,湖大臨時不搞了,新的考場機位不夠,只允許 csp2021 s 1 的初中生參加,親手葬送 noip 省選。退役是不可能的,ys 說盡力讓我參加明年省選,只要實力還在,一次 noip 不算什麼。想參加wc 具體原因請看 遊記 csp2021 s 遊記 湖大突然說不搞了,ys 讓我週六下午在小...