A线段树或者树状数组,离线处理,hash,数组开大些 hdu3333
#include <iostream>
#include <cstdio>
#include <string.h>
#include <map>
using namespace std;
#define MAXN 300000 + 10
map <__int64, int> hash;
int n, m;
__int64 val[MAXN], ans[MAXN], c[MAXN];
struct Node
{
int l, r, index;
}q[MAXN];
__int64 lowbit(int x)
{
return x & (-x);
}
__int64 sum(int n)
{
__int64 sum = 0;
while (n > 0)
{
sum += c[n];
n -= lowbit(n);
}
return sum;
}
void change(int i, __int64 x)
{
while (i <= n)
{
c[i] = c[i] + x;
i += lowbit(i);
}
}
bool cmp(Node a, Node b)
{
return a.r < b.r;
}
void input()
{
int t;
cin >> t;
while (t--)
{
scanf("%d", &n);
hash.clear();
memset(c, 0, sizeof(c));
for (int i = 1; i <= n; i++)
{
scanf("%I64d", &val[i]);
}
scanf("%d", &m);
for (int i = 0; i < m; i++)
{
scanf("%d %d", &q[i].l, &q[i].r);
q[i].index = i;
}
sort(q, q + m, cmp);
for (int i = 0, pos = 1; i < m; i++)
{
while (pos <= n && pos <= q[i].r)
{
if (hash[val[pos]])
{
change(hash[val[pos]], -val[pos]);
}
change(pos, val[pos]);
hash[val[pos]] = pos;
pos++;
}
ans[q[i].index] = sum(q[i].r) - sum(q[i].l - 1);
}
for (int i = 0; i < m; i++)
{
printf("%I64d\n",ans[i]);
}
}
}
int main()
{
input();
return 0;
}
B题 略
C题二分图匹配求最大独立集,二分图中最大独立集 = 节点数 - 最大匹配数 hdu3335
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <string>
using namespace std;
#define MAXN 1000 * 10
int n;
bool vis[MAXN];
int match[MAXN];
__int64 node[MAXN];
struct Edge
{
int u, v, next;
}edge[1000 * MAXN];
int head[MAXN], e;
void add(int u, int v)
{
edge[e].v = v;
edge[e].next = head[u];
head[u] = e++;
}
void init()
{
e = 0;
memset(head, -1, sizeof(head));
memset(match, -1, sizeof(match));
}
bool dfs(int u)
{
for (int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].v;
if (!vis[v])
{
vis[v] = true;
if (match[v] == -1 || dfs(match[v]))
{
match[v] = u;
return true;
}
}
}
return false;
}
int solve()
{
int res = 0;
for (int i = 0; i < n; i++)
{
memset(vis, false, sizeof(vis));
if (dfs(i))
{
res++;
}
}
return res;
}
void input()
{
int t;
cin >> t;
while (t--)
{
init();
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%I64d", &node[i]);
}
sort(node, node + n);
int temp = 0;
for (int i = 1; i < n; i++)
{
if (node[temp] != node[i])
{
node[++temp] = node[i];
}
}
n = temp + 1;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (node[j] % node[i] == 0)
{
add(i, j);
}
}
}
cout << n - solve() << endl;
}
}
int main()
{
input();
return 0;
}
D题 Kmp + dp
#include <iostream>
#include <string.h>
using namespace std;
#define MAXN 200000 + 100
int next[MAXN];
string str;
void getN()
{
next[0] = -1;
for (int i = 1, j = -1; i < str.length(); i++)
{
while (j >= 0 && str[i] != str[j + 1])
{
j = next[j];
}
if (str[i] == str[j + 1])
{
j++;
}
next[i] = j;
}
}
int c[MAXN];
void input()
{
int cases, n;
long long sum = 0;
cin >> cases;
while (cases--)
{
sum = 0;
memset(c, 0, sizeof(c));
cin >> n;
cin >> str;
getN();
for (int i = 0; i < n; i++)
{
next[i]++;
}
for (int i = 1; i <= n; i++)
{
c[i] = (c[next[i - 1]] + 1) % 10007;
sum = (sum + c[i]) % 10007;
}
cout << sum << endl;
}
}
int main()
{
input();
return 0;
}
EF题 略
G题 最短路 + dp 有重边
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <string>
using namespace std;
#define MAXN 150
#define inf 100000000
int c[MAXN][MAXN];
int val[MAXN];
int dp[10000 * MAXN];
void input()
{
int t;
int u, v, w, n, m;
cin >> t;
while (t--)
{
scanf("%d %d", &n, &m);
memset(dp, 0, sizeof(dp));
for (int i = 0; i <= n; i++)
{
for (int j = 0; j <= n; j++)
{
c[i][j] = (i == j ? 0 : inf);
}
}
for (int i = 0; i < m; i++)
{
scanf("%d %d %d", &u, &v, &w);
c[u][v] = c[v][u]= min(c[u][v], w);
}
for (int k = 0; k <= n; k++)
{
for (int i = 0; i <= n; i++)
{
for (int j = 0; j <= n; j++)
{
if (c[i][k] + c[k][j] < c[i][j])
{
c[i][j] = c[i][k] + c[k][j];
}
}
}
}
int sum = 0, v = 0;
for (int i = 1; i <= n; i++)
{
scanf("%d", &val[i]);
sum += val[i];
if (c[0][i] != inf)
{
v += c[0][i];
}
}
sum /= 2;
for (int i = 1; i <= n; i++)
{
if (c[0][i] != inf)
for (int j = v; j >= c[0][i]; j--)
{
dp[j] = max(dp[j], dp[j - c[0][i]] + val[i]);
}
}
bool ok = false;
for (int i = 1; i <= v; i++)
{
if (dp[i] > sum)
{
cout << i << endl;
ok = true;
break;
}
}
if (!ok)
{
cout << "impossible" << endl;
}
}
}
int main()
{
input();
return 0;
}
I题ac自动机 + dp
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <string>
#include <queue>
using namespace std;
#define MAXN 50 + 10
#define MAXNODE 500 + 10
char c[MAXN], str[MAXN];
struct Trie
{
int next[MAXNODE][4], fail[MAXNODE];
int ends[MAXNODE];
int root, L;
int newnode()
{
for (int i = 0; i < 4; i++)
{
next[L][i] = -1;
}
ends[L++] = 0;
return L - 1;
}
void init()
{
L = 0;
root = newnode();
}
int getch(char ch)
{
if (ch == 'A') return 0;
if (ch == 'C') return 1;
if (ch == 'G') return 2;
if (ch == 'T') return 3;
}
void inserts(char *ch)
{
int len = strlen(ch);
int now = root;
for (int i = 0; i < len; i++)
{
if (next[now][getch(ch[i])] == -1)
{
next[now][getch(ch[i])] = newnode();
}
now = next[now][getch(ch[i])];
}
ends[now]++;
}
void build()
{
queue <int> Q;
fail[root] = root;
for (int i = 0; i < 4; i++)
{
if (next[root][i] == -1)
{
next[root][i] = root;
}
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while (!Q.empty())
{
int now = Q.front();
Q.pop();
ends[now] += ends[fail[now]];
for (int i = 0; i < 4; i++)
{
if (next[now][i] == -1)
{
next[now][i] = next[fail[now]][i];
}
else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
int dp[MAXNODE][11 * 11 * 11 * 11 + 10];
int bit[4];
int num[4];
int solve()
{
int len = strlen(str);
memset(num, 0, sizeof(num));
for (int i = 0; i < len; i++)
{
num[getch(str[i])]++;
}
bit[0] = (num[1] + 1) * (num[2] + 1) * (num[3] + 1);
bit[1] = (num[2] + 1) * (num[3] + 1);
bit[2] = (num[3] + 1);
bit[3] = 1;
memset(dp, -1, sizeof(dp));
dp[root][0] = 0;
for (int a = 0; a <= num[0]; a++)
{
for (int b = 0; b <= num[1]; b++)
{
for (int c = 0; c <= num[2]; c++)
{
for (int d = 0; d <= num[3]; d++)
{
int s = a * bit[0] + b * bit[1] + c * bit[2] + d * bit[3];
for (int i = 0; i < L; i++)
{
if (dp[i][s] >= 0)
for (int k = 0; k < 4; k++)
{
if (k == 0 && a == num[0])continue;
if (k == 1 && b == num[1])continue;
if (k == 2 && c == num[2])continue;
if (k == 3 && d == num[3])continue;
dp[next[i][k]][s + bit[k]] = max(dp[next[i][k]][s + bit[k]],dp[i][s] + ends[next[i][k]]);
}
}
}
}
}
}
int ans = 0;
int st = num[0] * bit[0] + num[1] * bit[1] + num[2] * bit[2] + num[3] * bit[3];
for (int i = 0; i < L; i++)
{
ans = max(ans, dp[i][st]);
}
cout << ans << endl;
}
}ac;
void input()
{
int n, cases = 0;
while (cin >> n, n)
{
ac.init();
for (int i = 0; i < n; i++)
{
scanf("%s", c);
ac.inserts(c);
}
ac.build();
scanf("%s", str);
cout << "Case " << ++cases << ": ";
ac.solve();
}
}
int main()
{
input();
return 0;
}
J题 是否所给有向图中存在环 floyd求传递闭包,拓扑排序,tarjan求联通分量都可以解决
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <string>
using namespace std;
#define MAXN 200
int c[MAXN][MAXN];
void input()
{
int n, m, u, v;
while (cin >> n >> m, n)
{
memset(c, 0, sizeof(c));
for (int i = 0; i < m; i++)
{
scanf("%d %d", &u, &v);
c[u][v] = 1;
}
for (int k = 0; k < n; k++)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (c[i][k] && c[k][j])
{
c[i][j] = 1;
}
}
}
}
bool ok = true;
for (int i = 0; i < n; i++)
{
if (c[i][i])
{
ok = false;
break;
}
}
cout << (ok ? "YES" : "NO") << endl;
}
}
int main()
{
input();
return 0;
}