找出第K大的子串,重复的不计入node
这个数据范围可能有什么暴力能够艹过去吧,可是K放大的话这就是后缀自动机板子题啊= =ios
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> //#define ivorysi #define MAXN 5005 #define eps 1e-8 using namespace std; typedef long long int64; typedef double db; struct node { int len,cnt,f; node *par,*nxt[26]; }pool[MAXN * 3],*tail = pool,*root,*last; void Build_Sam(int len,int c) { node *nowp = tail++,*p; nowp->len = len; for(p = last ; p && !p->nxt[c] ; p = p->par) { p->nxt[c] = nowp; } if(!p) nowp->par = root; else { node *q = p->nxt[c]; if(q->len == p->len + 1) nowp->par = q; else { node *cp = tail++; *cp = *q;cp->cnt = 0;cp->len = p->len + 1; q->par = nowp->par = cp; for( ; p && p->nxt[c] == q ; p = p->par) p->nxt[c] = cp; } } last = nowp; } int c[MAXN]; node *que[MAXN * 3]; char s[MAXN]; int N,K,M; int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif root = last = tail++; scanf("%s%d",s + 1,&K); N = strlen(s + 1); for(int i = 1 ; i <= N ; ++i) { Build_Sam(i,s[i] - 'a'); } M = tail - pool; for(int i = 0 ; i < M ; ++i) { c[pool[i].len]++; } for(int i = 1 ; i <= N ; ++i) c[i] += c[i - 1]; for(int i = 0 ; i < M ; ++i) { que[c[pool[i].len]--] = &pool[i]; } for(int i = 1 ; i <= M ; ++i) que[i]->f = 1; for(int i = M ; i >= 1 ; --i) { for(int j = 0 ; j < 26 ; ++j) { if(que[i]->nxt[j]) que[i]->f += que[i]->nxt[j]->f; } } node *p = root; while(K > 0) { for(int i = 0 ; i < 26 ; ++i) { if(!p->nxt[i]) continue; if(K <= p->nxt[i]->f) { putchar('a' + i); p = p->nxt[i]; --K; break; } else K -= p->nxt[i]->f; } } putchar('\n'); }
给出可交换的两个位置,和一个排列,求最后能达成pi = i的位置chrome
直接用并查集维护连通性,判一下这个位置上的数和该到的位置和初始位置在不在一个联通块数组
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> //#define ivorysi #define MAXN 100005 #define eps 1e-8 #define pb push_back using namespace std; typedef long long int64; typedef double db; int N,M; int P[MAXN],fa[MAXN]; int getfa(int x) { return fa[x] == x ? x : fa[x] = getfa(fa[x]); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif scanf("%d%d",&N,&M); for(int i = 1 ; i <= N ; ++i) scanf("%d",&P[i]); for(int i = 1 ; i <= N ; ++i) fa[i] = i; int x,y; for(int i = 1 ; i <= M ; ++i) { scanf("%d%d",&x,&y); fa[getfa(x)] = getfa(y); } int cnt = 0; for(int i = 1 ; i <= N ; ++i) { if(getfa(P[i]) == getfa(i)) ++cnt; } printf("%d\n",cnt); }
给出一个黑棋N个白棋N个的排列,每一种颜色的球分别标上1 - N,每次能够交换相邻两个球,求白棋相对顺序正确而且黑棋相对顺序正确,所须要最少的步数ui
动态规划,dp[i][j]表示前边放了i个白棋和j个黑棋所须要的最少步数
dp[i][j] = min(dp[i - 1][j] + cost_w[i - 1][j] , dp[i][j - 1] + cost_b[i][j - 1])
cost_w[i][j]表示前面已经有i个白棋和j个黑棋,在序列末再填一个白棋所须要的步数,cost_b同理
这个能够用树状数组预处理出来spa
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <ctime> //#define ivorysi #define MAXN 2005 #define eps 1e-7 using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; int N,a[MAXN * 2]; char c[MAXN * 2][5]; int tr[2][MAXN],cost[2][MAXN][MAXN],dp[MAXN][MAXN]; int lowbit(int x) {return x & (-x);} void Insert(int id,int x) { while(x <= N) { tr[id][x]++; x += lowbit(x); } } int Query(int id,int x) { int res = 0; while(x > 0) { res += tr[id][x]; x -= lowbit(x); } return res; } void Solve() { scanf("%d",&N); for(int i = 1 ; i <= 2 * N ; ++i) { scanf("%s%d",c[i] + 1,&a[i]); } for(int i = 1 ; i <= 2 * N ; ++i) { if(c[i][1] == 'W') { for(int j = 0 ; j <= N ; ++j) { cost[0][a[i] - 1][j] = (i - 1) - Query(0,a[i] - 1) - Query(1,j); } Insert(0,a[i]); } else { for(int j = 0 ; j <= N ; ++j) { cost[1][j][a[i] - 1] = (i - 1) - Query(0,j) - Query(1,a[i] - 1); } Insert(1,a[i]); } } for(int i = 0 ; i <= N ; ++i) { for(int j = 0 ; j <= N ; ++j) { if(i == 0 && j == 0) continue; dp[i][j] = 0x7fffffff; if(i != 0) { dp[i][j] = min(dp[i][j],dp[i - 1][j] + cost[0][i - 1][j]); } if(j != 0) { dp[i][j] = min(dp[i][j],dp[i][j - 1] + cost[1][i][j - 1]); } } } printf("%d\n",dp[N][N]); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
有一只猫 锟 ,还有一个树(多么现实的故事),树上黑白两种颜色,猫能够选择一个点开始走,每秒能够选择两种事件中的一种
1.翻转当前点颜色
2.到一个相邻点,并必须翻转这个点的颜色code
树dp,分三个路径,G[u]表示从点出发到这个点的子树而且不回来,F[u]表示从这个点出发而且回到这个点,H[u]表示一条路径通过这个点而且起点和终点都在它的子树中事件
转移比较繁琐可是很显然,具体看代码get
#include <iostream> #include <cstdio> #include <vector> #include <set> #include <cstring> #include <ctime> #include <map> #include <algorithm> #include <cmath> #define MAXN 100005 #define eps 1e-8 //#define ivorysi #define pii pair<int,int> #define mp make_pair #define fi first #define se second using namespace std; typedef long long int64; typedef double db; int N; struct node { int to,next; }E[MAXN * 2]; int head[MAXN],sumE,sizW[MAXN]; int F[MAXN],G[MAXN],H[MAXN],ans,son[MAXN],fa[MAXN],Ah[MAXN]; char c[MAXN]; void add(int u,int v) { E[++sumE].to = v; E[sumE].next = head[u]; head[u] = sumE; } void addtwo(int u,int v) { add(u,v);add(v,u); } void dfs(int u) { if(c[u] == 'W') sizW[u] = 1; else sizW[u] = 0; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa[u]) { fa[v] = u; dfs(v); sizW[u] += sizW[v]; } } } void dfs1(int u,int fa) { int Sum = 0; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa && sizW[v]) { dfs1(v,u); ++son[u]; F[u] += F[v]; Sum += F[v]; } } if(!son[u] && c[u] == 'W') { G[u] = F[u] = 1;return; } F[u] += son[u] + 1; if(c[u] == 'W') F[u] += ((son[u] + 1) ^ 1) & 1; else F[u] += (son[u] + 1 & 1); G[u] = Sum; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa && sizW[v]) { G[u] = min(G[u],Sum - F[v] + G[v]); } } G[u] += son[u]; if(c[u] == 'W') G[u] += (son[u] ^ 1) & 1; else G[u] += son[u] & 1; G[u] = min(G[u],F[u]); H[u] = 0x7fffffff; if(son[u] != 1) { pii t = mp(0,0); for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa && sizW[v]) { if(F[v] - G[v] > t.se) t.se = F[v] - G[v]; if(t.se > t.fi) swap(t.se,t.fi); } } int tmp = c[u] == 'W' ? ((son[u] - 1) ^ 1) & 1 : (son[u] - 1) & 1; H[u] = Sum - t.fi - t.se + tmp + son[u] - 1; Ah[u] = tmp; } for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa && sizW[v]) { int tmp = Sum - F[v] + H[v] + 1 - Ah[v] + (Ah[v] ^ 1) + son[u]; int t = c[u] == 'W' ? (son[u] ^ 1) & 1 : son[u] & 1; if(tmp + t < H[u]) { H[u] = tmp + t;Ah[u] = t; } } } } void Init() { scanf("%d",&N); int u,v; for(int i = 1 ; i < N ; ++i) { scanf("%d%d",&u,&v); addtwo(u,v); } scanf("%s",c + 1); dfs(1); } void Solve() { ans = 0x7fffffff; dfs1(1,0); if(sizW[1] == 0) ans = 0; else if(sizW[1] == 1) ans = 1; else { for(int i = 1 ; i <= N ; ++i) { if(sizW[i] == sizW[1]) { ans = min(ans,G[i]); ans = min(ans,F[i]); ans = min(ans,H[i]); } } } printf("%d\n",ans); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }