2015 Multi-University Training Contest 10

5406 CRB and Apple

1.排序之后费用流

spfa用stack才能过

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 2e3+7;
const int MAXE = 2e6+7;
const int INF = 0x3f3f3f3f;
#define S 0
#define SS MAXN - 2
#define T MAXN - 1
int dist[MAXN],pre[MAXN],preid[MAXN],flow[MAXN],vis[MAXN],n;
int tot,head[MAXN],nxt[MAXE],to[MAXE],fee[MAXE],cap[MAXE];
pair<int,int> pr[MAXN];
void ADDEDGE(int u, int v, int _cap, int _fee){
nxt[tot] = head[u]; to[tot] = v; cap[tot] = _cap; fee[tot] = _fee;
head[u] = tot++;
nxt[tot] = head[v]; to[tot] = u; cap[tot] = 0; fee[tot] = -_fee;
head[v] = tot++;
}
bool spfa(){
memset(dist,0x3f,sizeof(dist));
dist[S] = 0;
flow[S] = INF;
memset(vis,0,sizeof(vis));
stack<int> que;
que.push(S);
while(!que.empty()){
int u = que.top();
que.pop();
vis[u] = 0;
for(int i = head[u]; i; i = nxt[i]){
if(!cap[i] or dist[to[i]]<=dist[u]+fee[i]) continue;
dist[to[i]] = dist[u] + fee[i];
flow[to[i]] = min(cap[i],flow[u]);
pre[to[i]] = u; preid[to[i]] = i;
if(!vis[to[i]]){
vis[to[i]] = 1;
que.push(to[i]);
}
}
}
return dist[T]!=INF;
}
int mcmf(){
int cost = 0;
while(spfa()){
int u = T;
cost += dist[T] * flow[T];
while(u!=S){
int p = pre[u], id = preid[u];
cap[id] -= flow[T];
cap[id^1] += flow[T];
u = pre[u];
}
}
return cost;
} void solve(){
scanf("%d",&n);
tot = 2;
for(int i = 1; i <= n; i++) scanf("%d %d",&pr[i].first,&pr[i].second);
sort(pr+1,pr+1+n,[](const pair<int,int> &A, const pair<int,int> &B){
return A.first==B.first ? A.second<B.second : A.first>B.first;
});
memset(head,0,sizeof(head));
ADDEDGE(S,SS,2,0);
for(int i = 1; i <= n; i++) ADDEDGE(SS,i,1,0);
for(int i = 1; i <= n; i++) ADDEDGE(i+n,T,1,0);
for(int i = 1; i <= n; i++) ADDEDGE(i,i+n,1,-1);
for(int i = 1; i <= n; i++) for(int j = i + 1; j <= n; j++) if(pr[i].second<=pr[j].second){
ADDEDGE(i+n,j,1,0);
}
printf("%d\n",-mcmf());
}
int main(){
int t;
for(scanf("%d",&t); t; t--) solve();
return 0;
}

2.排序之后问题变成找两个LIS且长度和最大

树状数组优化\(DP\)

\(dp[i][j]\)表示两个LIS最后位置的价值分别为\(i\)和\(j\)的答案最大值

先把所有\(delicious\)离散化

然后按高度排序\(apple\)

枚举每个\(apple\)

假设当前枚举的\(delicious\)为\(v\)

枚举\(i\)

状态转移为\(dp[v][i] = dp[i][v] = max\{d[i][j]\}(j\le v)\)

可以用树状数组来维护区间最大值

复杂度\(O(n^2\log n)\)

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1111;
#define lowbit(x) (x & -x)
int n,f[MAXN][MAXN];
pair<int,int> pr[MAXN];
vector<int> vec;
void update(int *f, int pos, int x){
while(pos<=n){
f[pos] = max(f[pos],x);
pos += lowbit(pos);
}
}
int query(int *f, int pos){
int ret = 0;
while(pos){
ret = max(ret,f[pos]);
pos -= lowbit(pos);
}
return ret;
}
int tmp[MAXN];
void solve(){
scanf("%d",&n);
vec.clear();
for(int i = 1; i <= n; i++) scanf("%d %d",&pr[i].first,&pr[i].second);
for(int i = 1; i <= n; i++) pr[i].first *= -1, vec.push_back(pr[i].second);
sort(pr+1,pr+1+n);
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
for(int i = 1; i <= n; i++) pr[i].second = lower_bound(vec.begin(),vec.end(),pr[i].second) - vec.begin() + 1;
memset(f,0,sizeof(f));
int ret = 0;
for(int i = 1; i <= n; i++){
int val = pr[i].second;
for(int j = 0; j <= n; j++) tmp[j+1] = query(f[j+1],val+1) + 1;
for(int j = 0; j <= n; j++){
ret = max(ret,tmp[j+1]);
update(f[j+1],val+1,tmp[j+1]);
update(f[val+1],j+1,tmp[j+1]);
}
}
printf("%d\n",ret);
}
int main(){
int T;
for(scanf("%d",&T); T; T--) solve();
return 0;
}

5407 CRB and Candies

显然要求的是\(LCM(C(n,0),C(n,1),C(n,2),\cdots ,C(n,n-1),C(n,n))\)

显然\(LCM(C(n,0),C(n,1),C(n,2),\cdots ,C(n,n-1),C(n,n)) = \frac{LCM(1,2,3,\cdots,n-1,n,n+1)}{n+1}\)

接下来就是要计算\(LCM(1,2,3,\cdots,n-1,n,n+1)\)

令\(f(n)=LCM(1,2,3,\cdots,n-1,n)\)

\(f(n) = \begin{cases} f(n-1)*p & n=p^k \\ f(n-1) & otherwise \end{cases}\)

递推计算就好了

复杂度\(O(n\log n)\)

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
typedef long long int LL;
const int MAXN = 1e6+7;
const int MOD = 1e9+7;
LL f[MAXN],inv[MAXN],p[MAXN];
bool npm[MAXN];
vector<LL> prime;
void preprocess(){
for(int i = 2; i < MAXN; i++){
if(!npm[i]) prime.push_back(i);
for(int j = 0; j < (int)prime.size(); j++){
if(i*prime[j]>=MAXN) break;
npm[i*prime[j]] = true;
if(i%prime[j]==0) break;
}
}
fill(begin(p),end(p),1);
inv[1] = 1;
for(int i = 2; i < MAXN; i++) inv[i] = (MOD-MOD/i) * inv[MOD%i] % MOD;
for(LL pm : prime) for(LL x = pm; x < MAXN; x *= pm) p[x] = pm;
f[1] = 1;
for(int i = 2; i < MAXN; i++) f[i] = f[i-1] * p[i] % MOD;
}
int main(){
preprocess();
int T;
for(scanf("%d",&T); T; T--){
int n; scanf("%d",&n);
printf("%I64d\n",f[n+1]*inv[n+1]%MOD);
}
return 0;
}

5408 CRB and Farm

5409 CRB and Graph

tarjan缩点之后变成树上的问题

对于树上的每一条边,要求这条边把树分成的两部分中分别一个点\(u,v\)且\(u<v\)并最大化\(u\),最小化\(v\)

可以发现如果确定了\(u\),那么\(v\)必然是\(u+1\)

先把缩点后的每个点标记为连通块内点标号的最大和最小值

然后把标号离散化

接下来对于每条边分割成的两部分,把一部分的点染黑,另一部分染白

接下来就是找最大的黑白交界处的点

这个可以用树上启发式合并配合set维护线段来做

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
const int INF = 0x3f3f3f3f;
int n,m,bccid[MAXN],dfn[MAXN],low[MAXN],num,idx,minnode[MAXN],maxnode[MAXN],nn;
int sz[MAXN],son[MAXN],st[MAXN],ed[MAXN],rdfn[MAXN],sonid[MAXN];
pair<int,int> ret[MAXN];
set<pair<int,int> > seg;
vector<int> vec;
struct Graph{
int head[MAXN],to[MAXN<<1],nxt[MAXN<<1],id[MAXN<<1],tot;
void clear(){ memset(head,255,sizeof(head)); tot = 0; }
void ADDEDGE(int u, int v, int eid){
to[tot] = v; nxt[tot] = head[u]; id[tot] = eid;
head[u] = tot++;
}
}GG,G;
void init(){
num = idx = 0;
GG.clear(); G.clear();
memset(dfn,0,sizeof(dfn));
memset(maxnode,0,sizeof(maxnode));
memset(minnode,INF,sizeof(minnode));
memset(ret,0,sizeof(ret));
vec.clear(); seg.clear();
}
stack<int> stk;
void tarjan(int u, int par){
dfn[u] = low[u] = ++idx;
stk.push(u);
for(int i = GG.head[u]; ~i; i = GG.nxt[i]){
int v = GG.to[i];
if(v==par) continue;
if(dfn[v]) low[u] = min(low[u],dfn[v]);
else{
tarjan(v,u);
low[u] = min(low[u],low[v]);
}
}
if(low[u]==dfn[u]){
int tp;
num++;
do{
tp = stk.top();
stk.pop();
bccid[tp] = num;
minnode[num] = min(minnode[num],tp);
maxnode[num] = max(maxnode[num],tp);
}while(tp!=u);
}
}
void rebuild(){
for(int u = 1; u <= n; u++){
for(int i = GG.head[u]; ~i; i = GG.nxt[i]){
int v = GG.to[i];
if(bccid[u]==bccid[v]) continue;
G.ADDEDGE(bccid[u],bccid[v],GG.id[i]);
}
}
}
void dfs(int u, int par){
sz[u] = 1; son[u] = 0;
st[u] = ++idx; rdfn[idx] = u;
for(int i = G.head[u]; ~i; i = G.nxt[i]){
int v = G.to[i];
if(v==par) continue;
dfs(v,u);
sz[u] += sz[v];
if(sz[v]>sz[son[u]]) son[u] = v, sonid[u] = G.id[i];
}
ed[u] = idx;
}
void insert(int x){
if(seg.empty()){
seg.insert(make_pair(x,x));
return;
}
auto p = seg.lower_bound(make_pair(x,x));
if(p==seg.end()){
advance(p,-1);
if(p->second!=x-1) seg.insert(make_pair(x,x));
else{
auto curseg = *p;
seg.erase(p);
curseg.second++;
seg.insert(curseg);
}
}
else if(p==seg.begin()){
if(p->first!=x+1) seg.insert(make_pair(x,x));
else{
auto curseg = *p;
seg.erase(p);
curseg.first--;
seg.insert(curseg);
}
}
else{
pair<int,int> curseg = make_pair(x,x);
if(p->first==x+1) curseg.second = p->second;
advance(p,-1);
if(p->second==x-1) curseg.first = p->first;
if(curseg.second!=x) seg.erase(make_pair(x+1,curseg.second));
if(curseg.first!=x) seg.erase(make_pair(curseg.first,x-1));
seg.insert(curseg);
}
}
void erase(int x){
auto p = seg.lower_bound(make_pair(x,x));
if(p!=seg.end() and p->first==x){
if(p->second==x) seg.erase(p);
else{
auto curseg = *p;
seg.erase(p);
curseg.first++;
seg.insert(curseg);
}
}
else{
advance(p,-1);
if(p->second==x){
auto curseg = *p;
seg.erase(p);
curseg.second--;
seg.insert(curseg);
}
else{
auto curseg = *p;
seg.insert(make_pair(curseg.first,x-1));
seg.insert(make_pair(x+1,curseg.second));
seg.erase(curseg);
}
}
}
pair<int,int> query(){
auto curseg = *seg.rbegin();
int ans = curseg.second==nn ? curseg.first - 1 : curseg.second;
return make_pair(vec[ans-1],vec[ans-1]+1);
}
void modify(int u, int x){ for(int i = st[u]; i <= ed[u]; i++){
if(x==1){
insert(minnode[rdfn[i]]);
if(minnode[rdfn[i]]!=maxnode[rdfn[i]]) insert(maxnode[rdfn[i]]);
}
else{
erase(minnode[rdfn[i]]);
if(minnode[rdfn[i]]!=maxnode[rdfn[i]]) erase(maxnode[rdfn[i]]);
}
}
}
void rua(int u, int par, int eid, bool clear){
for(int i = G.head[u]; ~i; i = G.nxt[i]){
int v = G.to[i];
if(v==par or v==son[u]) continue;
rua(v,u,G.id[i],true);
}
if(son[u]) rua(son[u],u,sonid[u],false);
for(int i = G.head[u]; ~i; i = G.nxt[i]){
int v = G.to[i];
if(v==par or v==son[u]) continue;
modify(v,1);
}
insert(minnode[u]);
if(minnode[u]!=maxnode[u]) insert(maxnode[u]);
if(!par) return;
ret[eid] = query();
if(clear) modify(u,-1);
}
void solve(){
scanf("%d %d",&n,&m);
init();
for(int i = 1; i <= m; i++){
int u, v;
scanf("%d %d",&u,&v);
GG.ADDEDGE(u,v,i); GG.ADDEDGE(v,u,i);
}
tarjan(1,0);
rebuild();
for(int i = 1; i <= num; i++) vec.push_back(minnode[i]), vec.push_back(maxnode[i]);
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
nn = vec.size();
for(int i = 1; i <= num; i++){
minnode[i] = lower_bound(vec.begin(),vec.end(),minnode[i]) - vec.begin() + 1;
maxnode[i] = lower_bound(vec.begin(),vec.end(),maxnode[i]) - vec.begin() + 1;
}
idx = 0; dfs(1,0);
rua(1,0,0,false);
for(int i = 1; i <= m; i++) printf("%d %d\n",ret[i].first,ret[i].second);
}
int main(){
int T; for(scanf("%d",&T); T; T--) solve();
return 0;
}
/*
test1:
6 6
1 2
2 5
2 3
1 4
4 6
6 1
ans:
5 6
5 6
3 4
0 0
0 0
0 0 test2:
9 10
1 2
1 4
1 5
2 6
2 3
3 5
6 7
7 8
7 9
8 9
ans:
0 0
4 5
0 0
5 6
0 0
0 0
6 7
0 0
0 0
0 0
*/

5410 CRB and His Birthday

二进制分组背包

每个物品第一次拿可以有额外的\(B[i]\)的价值

把第一次拿分成一种,后面拿的二进制分组即可

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 2222;
const int INF = 0x3f3f3f3f;
int m,n,A[MAXN],B[MAXN],w[MAXN],f[MAXN];
void solve(){
scanf("%d %d",&m,&n);
for(int i = 1; i <= n; i++) scanf("%d %d %d",&w[i],&A[i],&B[i]);
vector<pair<int,int>> vec;
for(int i = 1; i <= n; i++){
if(w[i]>m) continue;
vec.push_back(make_pair(A[i]+B[i],w[i]));
for(int bit = 1; bit * w[i] <= m; bit <<= 1) vec.push_back(make_pair(A[i]*bit,w[i]*bit));
}
memset(f,0,sizeof(f));
for(int i = 0; i < (int)vec.size(); i++){
for(int j = m; j >= vec[i].second; j--) f[j] = max(f[j],f[j-vec[i].second] + vec[i].first);
}
printf("%d\n",f[m]);
}
int main(){
int T;
for(scanf("%d",&T); T; T--) solve();
return 0;
}

5411 CRB and Puzzle

矩阵快速幂优化DP

并且在快速幂中记录对答案的贡献

复杂度\(O(n^3\log m)\)

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 55;
const int MOD = 2015;
int n,m;
struct Matrix{
int mat[MAXN][MAXN];
Matrix(int tag = 0){
for(int i = 0; i < MAXN; i++) for(int j = 0; j < MAXN; j++){
if(i==j) mat[i][j] = tag;
else mat[i][j] = 0;
}
}
Matrix operator*(const Matrix rhs){
Matrix ret(0);
for(int i = 0; i <= n; i++)
for(int j = 0; j <= n; j++)
for(int k = 0; k <= n; k++)
ret.mat[i][j] = (ret.mat[i][j] + mat[i][k] * rhs.mat[k][j]) % MOD;
return ret;
}
};
Matrix qpow(Matrix A, int b){
Matrix ret(1);
while(b){
if(b&1) ret = ret * A;
b >>= 1;
A = A * A;
}
return ret;
}
bool vis[MAXN][MAXN];
void solve(){
memset(vis,0,sizeof(vis));
scanf("%d %d",&n,&m);
for(int i = 1; i <= n; i++){
int num; scanf("%d",&num);
while(num--){
int x; scanf("%d",&x);
vis[i][x] = true;
}
}
Matrix M(0);
for(int i = 0; i <= n; i++) M.mat[i][0] = 1;
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) M.mat[i][j] = vis[i][j] ? 1 : 0;
Matrix ret = qpow(M,m);
int ans = 0;
for(int i = 0; i <= n; i++) ans += ret.mat[i][0];
printf("%d\n",ans%MOD);
}
int main(){
int T;
for(scanf("%d",&T); T; T--) solve();
return 0;
}

5412 CRB and Queries

动态区间第K大

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 3e5+7;
#define lowbit(x) (x&-x)
int n,q,A[MAXN];
struct Qeury{
int op,l,r,k,pos,x;
}Q[MAXN];
vector<int> vec;
struct PersistentSegmentTree{
int root[MAXN],ls[MAXN*40],rs[MAXN*40],sum[MAXN*40],tot;
stack<int> stk;
vector<int> vl,vr;
void clear(){ memset(root,0,sizeof(root)); tot = 0; }
int newnode(){
int node;
if(!stk.empty()) node = stk.top(), stk.pop();
else node = ++tot;
ls[node] = rs[node] = 0;
sum[node] = 0;
return node;
}
void upd(int L, int R, int &rt, int x){
if(!rt) rt = newnode();
sum[rt] += x / abs(x);
if(L+1==R) return;
int mid = (L+R) >> 1;
if(abs(x)<mid) upd(L,mid,ls[rt],x);
else upd(mid,R,rs[rt],x);
if(!sum[rt]) stk.push(rt), rt = 0;
}
void update(int pos, int x){
for(int i = pos; i <= n; i += lowbit(i)){
upd(1,vec.size()+1,root[i],x);
}
}
int cal(){
int ret = 0;
for(int rt : vl) ret -= sum[ls[rt]];
for(int rt : vr) ret += sum[ls[rt]];
return ret;
}
int _query(int L, int R, int k){
if(L+1==R) return L;
int suml = cal();
if(k<=suml){
for(int &rt : vl) rt = ls[rt];
for(int &rt : vr) rt = ls[rt];
return _query(L,(L+R)>>1,k);
}
else{
for(int &rt : vl) rt = rs[rt];
for(int &rt : vr) rt = rs[rt];
return _query((L+R)>>1,R,k-suml);
}
}
int query(int L, int R, int k){
vl.clear(); vr.clear();
for(int i = L - 1; i; i -= lowbit(i)) vl.push_back(root[i]);
for(int i = R; i; i -= lowbit(i)) vr.push_back(root[i]);
return _query(1,vec.size()+1,k);
}
}PST;
void solve(){
PST.clear();
vec.clear();
for(int i = 1; i <= n; i++) scanf("%d",&A[i]), vec.push_back(A[i]);
scanf("%d",&q);
for(int i = 1; i <= q; i++){
scanf("%d",&Q[i].op);
if(Q[i].op==1) scanf("%d %d",&Q[i].pos,&Q[i].x), vec.push_back(Q[i].x);
else scanf("%d %d %d",&Q[i].l,&Q[i].r,&Q[i].k);
}
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
for(int i = 1; i <= n; i++) A[i] = lower_bound(vec.begin(),vec.end(),A[i]) - vec.begin() + 1;
for(int i = 1; i <= q; i++){
if(Q[i].op==1) Q[i].x = lower_bound(vec.begin(),vec.end(),Q[i].x) - vec.begin() + 1;
}
for(int i = 1; i <= n; i++) PST.update(i,A[i]);
for(int i = 1; i <= q; i++){
if(Q[i].op==1){
PST.update(Q[i].pos,-A[Q[i].pos]);
PST.update(Q[i].pos,A[Q[i].pos] = Q[i].x);
}
else printf("%d\n",vec[PST.query(Q[i].l,Q[i].r,Q[i].k)-1]);
}
}
int main(){
while(scanf("%d",&n)!=EOF) solve();
return 0;
}

5413 CRB and Roads

因为是个\(DAG\),所以可以先拓扑排序

能删去的\(u\)所连出去的边(到\(v\)),必然是\(u\)能通过其他点间接到达\(v\)

我们只要通过拓扑序维护\(u\)能间接到达的点即可

复杂度是\(O(n^2)\)

\(bitset\)优化之后复杂度为\(O(\frac{n^2}{32})\)

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 2e4+7;
const int MAXM = 1e5+7;
bitset<MAXN> A[MAXN];
int n,m,deg[MAXN];
vector<int> rG[MAXN],G[MAXN];
void solve(){
scanf("%d %d",&n,&m);
for(int i = 1; i <= n; i++){
A[i].reset();
G[i].clear(); rG[i].clear();
}
for(int i = 1; i <= m; i++){
int u, v;
scanf("%d %d",&u,&v);
rG[v].push_back(u);
G[u].push_back(v);
deg[u]++;
}
queue<int> que;
for(int i = 1; i <= n; i++) if(!deg[i]) que.push(i);
int ret = 0;
while(!que.empty()){
int u = que.front();
que.pop();
for(int v : G[u]) if(A[u].test(v)) ret++;
for(int v : G[u]) A[u].set(v,1);
for(int v : rG[u]){
if(!--deg[v]) que.push(v);
A[v] |= A[u];
}
}
printf("%d\n",ret);
}
int main(){
int T; for(scanf("%d",&T); T; T--) solve();
return 0;
}

5414 CRB and String

思维+子序列自动机

先判断首字母是否相同,不相同则No

然后判断\(s\)和\(t\)头部最长相同字符长度,如果\(t\)的长度比\(s\)长则No

然后去掉开头\(s\)和\(t\)的匹配部分,判断剩下部分的\(s\)是否是剩下部分的\(t\)的子序列即可

复杂度\(O(Length)\)

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 2e5+7;
const int INF = 0x3f3f3f3f;
char s[MAXN],t[MAXN];
int ls,lt,f[MAXN][26]; void solve(){
scanf("%s %s",s,t);
ls = strlen(s); lt = strlen(t);
int match = 0;
int ms = 1, mt = 1;
while(s[ms-1]==s[ms]) ms++;
while(t[mt-1]==t[mt]) mt++;
if(s[0]!=t[0] or mt>ms){ puts("No"); return; }
match = mt;
memset(f[lt-1],0x3f,sizeof(f[lt-1]));
for(int i = lt - 2; i >= 0; i--){
for(int ch = 0; ch < 26; ch++) f[i][ch] = f[i+1][ch];
f[i][t[i+1]-'a'] = i + 1;
}
// check if s_match...s_ls-1 is a subsequence of t_match...t_lt-1
// subsequence automaton
int pos = match - 1;
bool ok = true;
for(int i = match; i < ls; i++){
if(f[pos][s[i]-'a']==INF){
ok = false;
break;
}
pos = f[pos][s[i]-'a'];
}
puts(ok?"Yes":"No");
}
int main(){
int T;
for(scanf("%d",&T); T; T--) solve();
return 0;
}

5415 CRB and Substrings

5416 CRB and Tree

可以把两点之间路径权值异或和转化为从根到两点的路径的权值异或和的异或和

复杂度\(O(TQN)\)

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 4e5+7;
typedef long long int LL;
int n,d[MAXN],cnt[MAXN];
vector<pair<int,int>> G[MAXN];
void dfs(int u, int f){
for(auto e : G[u]){
if(e.first==f) continue;
d[e.first] = d[u] ^ e.second;
dfs(e.first,u);
}
}
void solve(){
scanf("%d",&n);
for(int i = 1; i <= n; i++) G[i].clear();
for(int i = 1; i < n; i++){
int u, v, w;
scanf("%d %d %d",&u,&v,&w);
G[u].push_back(make_pair(v,w));
G[v].push_back(make_pair(u,w));
}
dfs(1,0);
memset(cnt,0,sizeof(cnt));
for(int i = 1; i <= n; i++) cnt[d[i]]++;
int q; scanf("%d",&q);
while(q--){
int x; scanf("%d",&x);
LL ret = 0;
for(int i = 1; i <= n; i++) ret += cnt[x^d[i]];
if(!x) ret += n;
printf("%I64d\n",ret>>1);
}
} int main(){
int T;
for(scanf("%d",&T); T; T--) solve();
return 0;
}

2015 Multi-University Training Contest 10(9/11)的更多相关文章

  1. 2015 Multi-University Training Contest 1(7/12)

    2015 Multi-University Training Contest 1 A.OO's Sequence 计算每个数的贡献 找出第\(i\)个数左边最靠右的因子位置\(lp\)和右边最靠左的因 ...

  2. hdu 5416 CRB and Tree(2015 Multi-University Training Contest 10)

    CRB and Tree                                                             Time Limit: 8000/4000 MS (J ...

  3. 2015 Multi-University Training Contest 10 hdu 5406 CRB and Apple

    CRB and Apple Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  4. 2015 Multi-University Training Contest 10 hdu 5412 CRB and Queries

    CRB and Queries Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  5. 2016 Multi-University Training Contest 10

    solved 7/11 2016 Multi-University Training Contest 10 题解链接 分类讨论 1001 Median(BH) 题意: 有长度为n排好序的序列,给两段子 ...

  6. [二分,multiset] 2019 Multi-University Training Contest 10 Welcome Party

    Welcome Party Time Limit: 4000/4000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)T ...

  7. 常量表达式和constexpr(c++11)

    常量表达式 常量表达式是指值不会改变且在编译阶段就能得到计算结果的表达式(两点要求) ; //是常量表达式 ; //是常量表达式 "; const int siz=s.size(); //不 ...

  8. (2.11)Mysql之SQL基础——存储过程与变量

    (2.11)Mysql之SQL基础——存储过程 关键字:mysql存储过程 查看存储过程: []SELECT * FROM information_schema.ROUTINES WHERE ROUT ...

  9. (1.11)SQL优化——mysql提示(hint)

    (1.11)mysql hint 关键词:mysql提示 1.SQL提示 (hint)是优化数据库的手段之一,使用它加入一些人为的提示来达到优化操作的目的: 举例: select sql_buffer ...

随机推荐

  1. keycloak集成微信登陆~解决国内微信集成的问题

    之前看了国内写的微信集成keycloak的文章,然后拿来就用了,但我的是jboss部署的keycloak,然后使用他的包之后,会出现类无法找到的问题,之后找了很多资料,多数都是国外的,在今天终于找到了 ...

  2. Docker踩过的坑

    前言 主要是记录Docker遇到的坑,更多的是因为自己的粗心大意,以此警示 正文 Dockerfile里的RUN 某一次把启动服务的命令写在了 Dockerfile 中,后来发现服务一直拉不起来. 原 ...

  3. innobackupex: Connecting to MySQL server with DSN 'dbi:mysql

    [root@ma src]# innobackupex --user=root /root/backup --no-timestamp InnoDB Backup Utility v1.5.1-xtr ...

  4. [翻译]Azure 网关迁移至 .NET Core 3.1 性能提升一倍

    原文:[Azure Active Directory's gateway is on .NET Core 3.1!] Azure Active Directory 的网关服务是一个反向代理,它为构成 ...

  5. 【Linux】rsync中sending incremental file list时间优化

    每次使用rsync的时候,前面出现sending incremental file list 这句之后要等待很长时间 查了很多帖子和官方文档后,发现是-c这个选项的问题, -v, --verbose ...

  6. dmp文件导入抽取方法

    一.确认dmp文件.oracle客户端和服务端的字符集 (1)dmp文件字符集确认: 使用UE打开dmp文件查看文件第2个和第3个字节内容,这两个字节记录了dmp文件的字符集.如0354,然后用以下s ...

  7. Lakehouse: 统一数据仓库和高级分析的新一代开放平台

    1. 摘要 数仓架构在未来一段时间内会逐渐消亡,会被一种新的Lakehouse架构取代,该架构主要有如下特性 基于开放的数据格式,如Parquet: 机器学习和数据科学将被作为头等公民支持: 提供卓越 ...

  8. 阅读lodash源码之旅数组方法篇-compact和concat

    鲁迅说过:只有阅读过优秀库源码的人,才能配的上是真正的勇士. compact 创建一个新数组,包含原数组中所有的非假值元素.例如false, null,0, "", undefin ...

  9. Java-web易混淆知识点整理

    Java-web易混淆知识点 post和get区别 post: 数据不会显示在地址栏 安全 大小无限制 可以提交二进制文件 get: 数据显示在地址栏 不安全 get方式提交有大小限制(约4kb) 相 ...

  10. bootstrap 轮播图带缩列图两端对齐,并自动换行然后左对齐!

    禁止自动轮播 data-interval="false" 完整代码如下: 1 <!DOCTYPE html> 2 <html> 3 4 <head&g ...