2019 2 28 雜題選講

2021-09-11 17:40:35 字數 3139 閱讀 8468

考慮將1至n × m分別填入乙個擁有n行m列的**中,不允許重複。

你需要滿足以下要求:

• 第i行(1≤ i ≤ n)的最大值為ai。

• 第j列(1≤ j ≤ m)的最大值為bj。

請求出合法的填數方案數在模109+7意義下的值。

• 1 ≤ n, m ≤ 1000

• 1 ≤ ai, bj ≤ n × m

思路分步(填數)問題符合乘法原理,考慮從大到小填數,先填大數承包一行(列)的最大值可保證後填的數不受到影響。

乙個數兩次以上出現則無解。

乙個數出現乙個,說明它只能填在限定的行(列),並且滿足它的列(行)已經被更大的數覆蓋。

乙個數沒有出現過,類似,填在已經覆蓋的格中。

提交記錄

#include

#define n 1010

#define mod 1000000007

using

namespace std;

int n,m,a[n]

,b[n]

;int cnt[n*n]

,backa[n*n]

,backb[n*n]

,line=

0,row=

0,writen=

0,zero=0;

long

long ans=1;

intmain()

else

if(backa[num]

)else

if(backb[num]

)else}if

(zero)

printf

("0\n");

else

printf

("%lld\n"

,ans)

;return0;

}

現有n個點。第i個點的權值為ai 。你要將這n個點連線成一棵樹。

在第i個點和第j個點之間連邊的代價是|i-j| × d+ai+aj 。請找出總代價的最小可能值。

• 1≤ n≤ 2 × 105

• 1≤ d≤ 109

• 1≤ ai ≤ 109

思路分治加邊提取出可能有貢獻的邊後再做最小生成樹。

對於區間 [ l ,r ] , 下標有序,去絕對值,左半邊貢獻為 a[i]-d * i ,右半邊貢獻為 a[i]+d * i ,連線左右區間的邊必定其中乙個端點為左邊貢獻最小的點或者右邊貢獻最小的點,這樣的邊有 o(n) 條,層數 o(logn),邊數 o(nlogn),時間複雜度o(nlognlogn)

提交記錄

#include

#define n 200020

#define logn 20

using

namespace std;

int n,first[n]

,nxt[n*logn*15]

,tot=0;

long

long ans,a[n]

,inf=

1e18

,d;int fa[n]

,cnt=0;

long

long

read()

while

(c>=

'0'&&c<=

'9')

return f*x;

}struct edge

edge[n*logn*15]

;bool

cmp(

const edge a,

const edge b)

void

add(

int u,

int v)

;return;}

intbuild

(int l,

int r,

int flag)

intget

(int x)

void

join

(int x,

int y)

long

long

krus()

}return ret;

}int

main()

有乙個n個點m條邊的無向聯通圖,點有點權,邊有邊權。

問至少刪去多少條邊,使得對於剩下的每一條邊,它所在的聯通塊的點權值和大於等於該

邊的邊權。

• 1≤ n, m≤ 105

思路反著加邊,維護乙個sum是乙個聯通塊內不滿足要求的邊數,由於是從小到大加邊,可以保證每次更新答案都是合法

提交記錄

#include

#define n 100010

using

namespace std;

int n,m,first[n]

,nxt[n<<1]

,tot=0;

int fa[n]

,sum[n]

,x,y,z,ans=0;

long

long w[n]

;long

long

read()

while

(c>=

'0'&&c<=

'9')

return f*x;

}struct edge

edge[n<<1]

;bool

cmp(

const edge a,

const edge b)

void

add(

int u,

int v,

int w)

;return;}

intget

(int x)

void

join

(int x,

int y)

intmain()

for(

int i=

1;i<=n;i++

) fa[i]

=i;sort

(edge+

1,edge+tot+

1,cmp)

;for

(int i=

1;i<=tot;i++

)printf

("%d\n"

,m-ans)

;return0;

}

(未完待續)

雜題選講1 2

把序列排序後 問題轉化為子串行兩兩之間的異或和大於等於k 使用者 trie 樹優化 dp 因為不滿足單調性所以不能用二分來優化 從實際含義入手 ans n 2 sum d1 i dk i sum j k 線性預處理即可 複雜度 o n t 原先做 sa 的題時用過這個套路 列舉長度 len 2 每隔...

9 26雜題選講

非常開心,所有 都咕掉了 cy 簡單計數題,樹狀陣列維護即可。線段樹維護,如果乙個區間整除某個數的時候都等價於減同乙個數,那麼就打上區間減法的標記。複雜度玄學,但是能過。把正著做換成倒著做,把操作變成減去兩邊的數。考慮最大的那個數,顯然在它沒有變化的情況下兩邊的數都不能進行操作,所以如果它沒有變成目...

5 30雜題選講

前三題為水題,後面兩題更有意思。然而 全都咕咕咕了,也許以後會補。簡單樹形dp。簡單最短路。簡單數字dp。首先對於每個點,可行的區域顯然是個矩形,那麼可以先對這些矩形求交,得到合法區域。如果不考慮限制,那麼最優點顯然是 x,y 的中位數。考慮限制之後,只要定下 x 那麼最優的 y 也是確定的。而且,...