NOIP2021 棋局 題解

2022-09-20 07:21:13 字數 4806 閱讀 6520

由於存在相對顏色大小關係,我們考慮線段樹合併來維護這個結構。

為了後續的討論的方便,我們將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 讓我週六下午在小...