按照時間軸建一棵線段樹即可,複雜度為\(o(m \log m)\)
#include #define n 100005
#define ll long long
#define getchar nc
using namespace std;
inline char nc()
inline ll read()
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}inline void write(register int x)
int n;
ll mod;
struct segmenttree
inline void pushup(register int x)
inline void update(register int x,register int l,register int r,register int pos,register int v)
int mid=l+r>>1;
if(pos<=mid)
update(x<<1,l,mid,pos,v);
else
update(x<<1|1,mid+1,r,pos,v);
pushup(x);
}}tr;
int main()
} return 0;
}
考慮二分答案,二分的是最大能覆蓋到的權值
這樣我們就將問題轉化成乙個dag能否被\(n+1\)條可重鏈覆蓋
這就是乙個經典問題了,先跑一下弗洛伊德傳遞閉包,然後二分圖最大匹配即可,複雜度為\(o(m^3+m^3 \log m )\)
#include #define n 505
#define getchar nc
using namespace std;
inline char nc()
inline int read()
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}inline void write(register int x)
int n,m,o[n],v[n],g[n][n],gn[n][n],link[n],vis[n];
inline bool hungary(register int x)
return 0;
}inline bool check(register int mid)
memset(link,0,sizeof(link));
for(register int i=1;i<=m;++i)
return res<=n;
}int main()
for(register int k=1;k<=m;++k)
for(register int i=1;i<=m;++i)
for(register int j=1;j<=m;++j)
g[i][j]|=g[i][k]&g[k][j];
sort(o+1,o+m+1);
if(check(o[m]+1))
int l=1,r=m-1;
while(l>1;
if(check(o[mid]))
l=mid;
else
r=mid-1;
}write(o[l+1]);
return 0;
}
這題和麻將是乙個套路,考的是乙個叫做dp套dp的神奇科技
發現獎章串的長度小於等於15,所以可以考慮把15位的dp陣列作為轉移的狀態
回想一下lcs的求法,dp相鄰的兩個值最多差1,可以考慮狀壓
設\(f[i][j][0/1/2]\)表示匹配到兌獎串的第\(i\)位,\(dp\)狀態為j,最後與「noi」的匹配位數為0/1/2,轉移顯然
直接做空間會炸,第一位滾一下即可,複雜度為\(o(nk2^k)\)
#include #define mod 1000000007
#define n 1005
using namespace std;
inline int read()
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}inline void write(register int x)
inline void add(register int &x,register int y)
int n,l,tot;
char s[20];
int dp[2][n],f[2][1<<15][3],ans[n];
inline void decode(register int sta)
inline int encode()
inline void trans(register int i,register int j,register int k,register char c,register int v)
add(f[i][encode()][k],v);
}int main()
\)表示處理完了\(i\)個鹼基序列,匹配到第\(j\)位的方案數,轉移顯然
空間不夠,滾動一下即可,複雜度為\(o(t \sum a_i |s|)\)
#include #define mod 1000000007
#define n 100005
using namespace std;
inline int read()
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}inline void write(register int x)
int m,n,f[2][n],now,nxt[n],ans;
char s[n],t[n];
int main()
inline int read()
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}inline void write(register int x)
inline int max(register int a,register int b)
struct edgee[n<<1];
int head[n],cnt=0;
inline void add(register int u,register int v)
; head[u]=cnt;
}int n,q,v[n],root[n];
int son[n],fa[n],size[n],dep[n],top[n],dfn[n],tim;
struct nodetr[n*80];
int tot=0;
inline void insert(register int &rt,register int pre,register int bit,register int val)
inline int query(register int a,register int b,register int bit,register int val)
int main()
^ i^\]則
\[ans=\sum_^\left(s\left(n-a_\right)-\sum_^\left(a_-a_\right)^\right)
\]珂以證明\(s(x)\)是個\(m+3\)次多項式(珂以用一次二次三次函式模擬,但嚴謹的證明還是需要通過數學歸納法的),可以用拉格朗日插值快速處理,複雜度為\(o(t m^2 \log p)\),預處理逆元的話能做到\(o(t m^2)\)
#include #define ll long long
#define mod 1000000007
#define n 55
#define getchar nc
using namespace std;
inline char nc()
inline ll read()
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}inline void write(register int x)
inline int power(register ll a,register int b)
return res;
}ll t,n,m,a[n],f[n];
inline int calc(register ll d,register int n)
return (ans+mod)%mod;
}int main()
write(ans),puts("");
}return 0;
}
題解 TJOI2018 異或
對於題目給出的兩個查詢,我們我可以將它這樣轉換 對於操作一,用dfs序將乙個子樹轉化為一段連續的區間,然後根據dfs序建立乙個trie樹,那麼查詢乙個子樹即為查詢一段區間 對於操作二,根據根到結點的路徑建立乙個trie樹,同樣也可以轉化為乙個區間查詢 於是就可以建兩個trie樹,分別對應兩個操作 結...
TJOI2018 數學計算
如果採取暴力的做法,那麼乘起來會炸longlong,除非寫個高精。再考慮乘一下逆元呢,顯然也不行,模數不一定為質數。這道題的關鍵點在於這句話,對於每乙個型別1的操作至多會被除一次 這句話的最基本的告訴了我們每次得到的答案一定是乙個整數 其次,這句話保證了可以應用線段樹解決這個問題 如果除的操作可能會...
Tjoi2018 數學計算
bzoj luogu 線段樹分治 是不是想問為什麼不暴力做?模數沒說是質數,所以不一定有逆元.然後就是要每次build一下把線段樹權值init成1,博豬不知道為什麼for就wa,build就過了 用re自動機查了下,發現還是有0.for int i 1 i 1 i s i 1 define ls x...