NOIP 模擬17 題解

2022-03-16 16:57:26 字數 2859 閱讀 2902

部分分很肥,正解寫得常數稍大就會和暴力乙個分,考試的時候寫什麼自己考慮。(滑稽

部分分的迴圈邊界手抖寫錯了-25 (原本暴力分中的10分都沒了啊啊啊)

沒寫掛的話應該有75,其實就是二維字首和+暴力列舉點對統計+$a[i][j]$都相等時只枚舉子矩形大小再乘上這種大小出現的次數。

正解:$(sum[r]-sum[l-1])\% k=0 \rightarrow sum[r]\% k=sum[l-1]\% k$

枚舉行數$i,j$和列數$k$,維護i行和j行之間、k列左側在%k意義下同餘矩陣的個數,用桶來實現。

#include#include

#include

using

namespace

std;

typedef

long

long

ll;const

int n=650

;int

n,m;

ll k,ans;

inta[n][n];

ll sum[n][n],sum1[n],cnt[

1000005

];int

read()

while(isdigit(ch))x=x*10+ch-'

0',ch=getchar();

return x*f;

}int

main()

for(int k=1;k<=m;k++)cnt[sum1[k]]=0

; }

cout

return0;

}

view code

我考場都能想到的sb貪心。每次取出深度最大且未被覆蓋的點,在它的k級祖先上駐紮即可。前者用堆維護,後者直接暴力修改覆蓋狀態,注意向上修改時不要只遍歷和它在一條鏈上的。

正確性?讀者自證不難。(逃

#include#include

#include

#include

#define pa pair#define re register

using

namespace

std;

intread()

while(isdigit(ch))x=x*10+ch-'

0',ch=getchar();

return x*f;

}const

int n=100005

;int

n,k,t;

int to[n<<1],nxt[n<<1

],head[n],tot;

inline

void add(int x,int

y)int

dep[n],fa[n];

priority_queue

q;void dfs1(int x,int

deep)

return;}

intcover[n],anc,ans;

void getan(int x,int

rest)

getan(fa[x],rest-1

);

return;}

void dfs2(int x,int rest,int

f)

return;}

intmain()

dfs1(

1,1);

for(re int i=1;i<=n;i++)

q.push(make_pair(dep[i],i));

while(!q.empty())

cout

return0;

}

view code

區間狀態反轉可以看作區間異或1,但區間操作不好處理,考慮通過差分轉化為單點操作。即把對原陣列上$[l,r]$區間的操作轉化為差分陣列上$l-1$和$r$兩個點的操作。這裡用到了異或差分:$dif[i]=a[i]\ xor\ a[i+1]$

所以問題變成了:有乙個01串,每次對其中兩個點$xor\ 1$,需要多少次把這個串的每一位都變成0。(差分陣列全0對應原陣列全1)

可以發現,消去兩個1的費用與他們之間的距離有關。bfs預處理出來後,問題再次得到轉化:每次取出一對物品,每對物品取出都有一定代價,如何取出使得代價最小。由於不亮的燈泡很少,這個問題完全可以狀壓解決。

#include#include

#include

#include

#include

using

namespace

std;

intread()

while(isdigit(ch))x=x*10+ch-'

0',ch=getchar();

return x*f;

}const

int n=40005

;int

n,m,k;

inta[n],op[n],dif[n];

intpos[n],sz;

int vis[n],dis[20][20

],d[n];

int find0[n<<1],dp[n<<1

];void bfs(int

node)

if(s2>=0&&!vis[s2])}}

}int

main()

for(int i=1;i<=sz;i++)

for(int s=0;s

}memset(dp,

0x3f,sizeof

(dp));

dp[0]=0

;

for(int s=0;s

for(int i=find0[s]+1;i)

}cout

<1

<1]<

return0;

}

view code

模擬17 題解

t1 a.入陣曲 60 演算法 維護一下某一列的從第一行到這一行和二維字首和 然後列舉上下左右邊界,o n 4 100 演算法 省掉左右邊界的列舉,改為從左向右掃一邊,記錄總和 k的餘數,並放入桶中,可以發現,如果這個值出現過,那說明這個位置的總和減去那個位置的差 即這個區間 是k的正倍數 t2又是...

NOIP模擬20 題解

來自達哥的問候 究級難題,完全不可做qaq include include include using namespace std typedef long long ll int n ll a 25 b 25 c 25 d 25 ans void dfs int step,ll mdx,ll lh...

NOIP模擬16 題解

出題人大概已經去為國家處理積壓子彈了?貪心,讓每乙隻青蛙 我慫行吧 都盡量往遠跳,能到達的最遠的被踩了就跳次遠的,以此類推。可以維護乙個單調佇列,表示每只青蛙的位置 開始都是0 然後按順序掃一遍每個石頭,如果隊首的青蛙不能跳過去就放棄它直接pop掉,如果能跳就把石頭位置從隊尾push進去並pop掉隊...