聽學長說有比賽就隨便打一打。
a.普通計算姬
題目大意:給出一棵帶權樹,支援一下兩種操作:1.修改乙個點的權值;2.給出l,r,詢問以點l為根的子樹和、點l+1為根的子樹和、點l+2為根的子樹和……點r為根的子樹和的總和。(點數、運算元不超過10^5)
思路:感覺是三題中最難的。給出的[l,r]區間在樹上沒有實際意義,不好利用資料結構維護。考慮若不修改,可以一遍dfs算出每個點對應的dfs序,這樣每棵子樹都對應乙個dfs序的區間,字首和一下就能o(1)查子樹和,再按點的編號順序把子樹和字首和一下就能o(1)回答詢問,若要支援修改,我們可以分塊重構,每次修改我們先只記錄下有這次修改而不實際修改字首和陣列,詢問時先利用之前的字首和陣列計算答案,再統計之前每一次修改對這次詢問的貢獻;每進行k次修改,我們就o(n)重建一遍字首和陣列並刪掉記錄下的修改。統計修改對詢問的貢獻可以這麼做:將每個子樹對應成dfs序區間,統計詢問區間內有多少個dfs序區間包含修改點,可以用主席樹求出詢問區間內有多少dfs序區間右端點大等於修改點,減去有多少dfs序區間左端點大於修改點就得到包含修改點的區間個數,就能計算貢獻了。總複雜度o(n^2/k+knlogn),適當調整k的大小複雜度約為o(n(nlogn)^0.5)。
#include#define ll unsigned long longinlineintread()
#define mn 100000
#define mk 50
#define nd 4000000
struct edgee[mn*2+5
];struct nodet[nd+5
];int n,h[mn+5],en,z[mn+5],l[mn+5],r[mn+5],cnt,cx[mn+5],cy[mn+5],cn,tn,rt[mn+5
];ll a[mn+5],b[mn+5
];inline
void ins(int x,int
y);h[x]=en;
e[++en]=(edge);h[y]=en;
}void dfs(int x,int
fa)void
build()
void ins(int pr,int pl,int x,intz)}
int query(int pl,int pr,intx)}
intmain()
if(t==2
)
}}
b.文藝計算姬
題目大意:求一邊有n個點,另一邊有m個點,共n*m條邊的二分圖共有多少種生成樹,答案對p取模。(n,m,p<=10^18)
思路:先用矩陣樹定理暴力計算一部分答案,觀察容易發現答案為n^(m-1)*m^(n-1),由於模數較大乘法會爆long long,要用類似快速冪的快速乘加上快速冪,複雜度為o(logp^2)。答案公式我還沒想到比較好的證明方法,想到了會在這裡補上(這類題目一般打表才是比較好的做法)。
矩陣樹定理暴力的**好像被誤刪了,本來想貼出來的……
#include#define ll long longll n,m,p;inline ll mod(ll x)
ll mul(ll a,ll b)
ll pow(ll a,ll b)
intmain()
c.兩雙手
題目大意:乙個棋子從(0,0)開始走,每次可以從(u,v)走到(u+ax,u+ay)或(u+bx,u+by),有n個點不能走,問走到(ex,ey)有多少種方案。(0<=|ax|,|ay|,|bx|,|by|,ex,ey,n<=500,ax*by-ay*bx!=0)
思路:比較雜的數學應用吧。考慮容斥原理,走到(ex,ey)不經過禁止點的方案=總方案-至少經過乙個禁止點的方案+至少經過兩個-至少經過三個……可以用dp實現,為了讓點有序方便dp,假設先把所有點旋轉,使得向量(ax,ay)成為x軸,若(bx,by)旋轉後的縱座標大於0,則乙個點可以到另乙個當且僅當該點旋轉後縱座標小於另一點旋轉後縱座標,反之同理,按照這個思路排序(實現上比較點積叉積等即可),我們就能保證只有排在前的能到達排在後的。經過奇數個點對答案貢獻為負,偶數貢獻為正,每次轉移取負即可,令f[i]表示到第i個點的答案,則f[i]=σ-f[j]*g[j][i] (j
#include#includeusing
namespace
std;
#define mn 500
#define mx 500000
#define mod 1000000007
int g[mn+5][mn+5],f[mx+5],r[mx+5],f[mn+5
],a,b,c,d,e;
int inv(int
x)struct nodep[mn+5
];bool
cmp(node x,node y)
intmain()
for(i=0;i<=n+1;++i)
}
BZOJ十連測 線段樹
在若干次操作後,某乙個位置的值可以表示成若干各區間的最大值。例如位置k kk,我們找到當前操作前最後乙個 編號最大但小於當前編號 覆蓋當前區間左端點的操作的左端點,最後乙個覆蓋當前當前區間右端點的操作的右端點,把這個左右端點當成乙個新的操作區間,然後重複執行上述操作。也就是我們需要一直向左找,一直向...
BFS BZOJ省選十連測 Cycle
蛤?這題絕對有問題。複雜度明顯不對頭。它的想法其實就是找到乙個點,判斷它與它周圍的點能否構成環,然後不能再刪去這個點。然而。他每次都memset了一發,這不t?服都服了。include include include include define sf scanf define pf printf ...
bzoj十連測第二場 A 深邃
一棵樹每個節點有顏色。請將樹分成若干連通塊,使每個連通塊均包含黑點。最小化最大的連通塊的大小。看到雙最直接二分。二分了乙個k,接下來怎麼判定?設f i 表示以i為根的情況 1 f i 為正數,表示以i為根的子樹內除了i所在連通塊均合法,i所在連通塊包含黑點時i所處連通塊大小的最小值。2 f i 為負...