A
题意:i 猴子 喜欢 j类型的水果, j类型的水果位于 k位置,问所有猴子喜欢类型的水果在什么地方能找到
思路:把喜欢类型j的水果压到同一个数组里面,然后对于j类型水果喜欢k说过,直接再对猴子进行加答案
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 50 + 10;
const int INF = 1e9 + 10;
vector<int> G[qq];
set<int> st[qq];
int n, m;
int main(){
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int a, b, i = 0; i < n; ++i) {
scanf("%d%d", &a, &b);
G[b].pb(a);
}
for(int a, b, i = 0; i < m; ++i) {
scanf("%d%d", &a, &b);
for(int j = 0; j < (int)G[a].size(); ++j) {
st[G[a][j]].insert(b);
}
}
set<int>::iterator it;
for(int i = 0; i <= 50; ++i) {
if(st[i].size() == 0) continue;
for(it = st[i].begin(); it != st[i].end(); ++it) {
printf("%d %d\n", i, *it);
}
}
for(int i = 0; i <= 50; ++i) {
G[i].clear();
st[i].clear();
}
puts("");
}
return 0;
}
C
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2e5 + 10;
const int INF = 1e9 + 10;
int n, b;
int c[qq];
int main(){
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &b);
for(int i = 1; i <= n; ++i) {
scanf("%d", c + i);
}
bool flag = true;
int sum = c[1];
for(int x, i = 2; i <= n; ++i) {
scanf("%d", &x);
if(sum - x * b >= 0) {
sum -= x * b;
sum += c[i];
} else {
flag = false;
}
}
if(!flag) puts("No");
else puts("Yes");
}
return 0;
}
E
队友打表打出来的结果
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
const int MOD = 1e9 + 7;
LL a[25]={1,8,49,288,1681,9800,57121,332928,1940449,
11309768,65918161,384199200,2239277041,13051463048,
76069501249,443365544448,2584123765441,15061377048200,
87784138523761,511643454094368,2982076586042449};
int main() {
int t,cas=1;
scanf("%d",&t);
while(t--) {
LL n;
scanf("%lld",&n);
for(int i=0;i<21;i++)
if(n<=a[i]) {
printf("Case #%d: %lld\n",cas++,a[i]);
break;
}
}
return 0;
}
F
题意:问最少加多少天边整个图能成为强联通图
思路:Tarjan缩点后统计入度为0的个数和出度为0的个数,取最大值即可
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e4 + 10;
const int INF = 1e9 + 10;
int belong[qq], dfn[qq], low[qq], Stack[qq];
int ind[qq], outd[qq];
bool instack[qq];
int n, m, Bcnt, Time, top;
vector<int> G[qq];
void Init() {
mst(instack, false);
mst(dfn, 0);
Bcnt = Time = top = 0;
for(int i = 0; i <= n; ++i) {
G[i].clear();
}
mst(ind, 0);
mst(outd, 0);
}
void Tarjan(int u) {
low[u] = dfn[u] = ++Time;
Stack[++top] = u;
instack[u] = true;
int sz = G[u].size();
for(int i = 0; i < sz; ++i) {
int v = G[u][i];
if(!dfn[v]) {
Tarjan(v);
low[u] = min(low[u], low[v]);
} else if(instack[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if(low[u] == dfn[u]) {
++Bcnt;
int v;
do {
v = Stack[top--];
instack[v] = false;
belong[v] = Bcnt;
}while(v != u);
}
}
int main(){
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
Init();
for(int a, b, i = 0; i < m; ++i) {
scanf("%d%d", &a, &b);
G[a].pb(b);
}
for(int i = 1; i <= n; ++i) {
if(!dfn[i]) Tarjan(i);
}
if(Bcnt == 1) {
printf("0\n");
continue;
}
for(int i = 1; i <= n; ++i) {
int sz = G[i].size();
for(int j = 0; j < sz; ++j) {
if(belong[i] == belong[G[i][j]]) continue;
outd[belong[i]]++;
ind[belong[G[i][j]]]++;
}
}
int a = 0, b = 0;
for(int i = 1; i <= Bcnt; ++i) {
if(ind[i] == 0) a++;
if(outd[i] == 0) b++;
}
printf("%d\n", max(a, b));
}
return 0;
}
G
题意:给出n次操作,Q 表示询问区间l r内有多少个字符串T, C 表示把S字符串中某一个位置的字符改变
思路:注意到T最大也只有10,所以我们可以考虑暴力更新,如果某一个位置的字符改变,最多会影响连续的|T|个串,所以我们每次更改的时候只需要对这部分进行更新即可,用树状数组维护前缀和
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e5 + 10;
const int INF = 1e9 + 10;
int sum[qq], num[qq];
int n, m;
char S[qq], T[20];
char a[5], b[5];
bool Isequal(int l, int r, int x, int y) {
int cur = x;
for(int i = l; i <= r; ++i, ++cur) {
if(S[i] != T[cur]) return false;
}
return true;
}
void UpDate(int x, int val, int lens) {
while(x <= lens) {
sum[x] += val;
x += x & (-x);
}
}
int GetSum(int x) {
int ans = 0;
while(x > 0) {
ans += sum[x];
x -= x & (-x);
}
return ans;
}
int main(){
int t; scanf("%d", &t);
while(t--) {
mst(sum, 0);
mst(num, 0);
scanf("%d", &n);
scanf("%s%s", S + 1, T + 1);
int lens = strlen(S + 1);
int lent = strlen(T + 1);
for(int i = lent; i <= lens; ++i) {
if(Isequal(i - lent + 1, i, 1, lent)) {
num[i] = 1;
} else {
num[i] = 0;
}
// printf("%d", num[i]);
if(num[i]) UpDate(i, 1, lens);
}
for(int i = 0; i < n; ++i) {
scanf("%s", a);
if(a[0] == 'Q') {
int l, r; scanf("%d%d", &l, &r);
if(r - l + 1 < lent) {
puts("0");
continue;
}
printf("%d\n", GetSum(r) - GetSum(l + lent - 1 - 1));
} else {
int pos; scanf("%d", &pos);
scanf("%s", a);
if(a[0] == S[pos]) continue;
S[pos] = a[0];
for(int j = pos; j < pos + lent && j <= lens; ++j) {
if(j - lent + 1 < 1) continue;
if(Isequal(j - lent + 1, j, 1, lent)) {
if(!num[j]) {
num[j] = 1;
UpDate(j, 1, lens);
}
} else {
if(num[j]) {
num[j] = 0;
UpDate(j, -1, lens);
}
}
}
/*for(int j = 1; j <= lens; ++j) {
printf("%d", num[j]);
}*/
}
}
puts("");
}
return 0;
}
H
题意:求有向图的最长链
思路:dp[i]代表以i结尾的最长链,然后我们可以借助有向图的拓扑结构更新答案
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e4 + 10;
const int INF = 1e9 + 10;
vector<int > G[qq], f[qq];
int deg[qq], dp[qq];
int n, m;
void Bfs() {
queue<int> Q;
for(int i = 1; i <= n; ++i) {
if(deg[i] == 0) Q.push(i);
}
while(!Q.empty()) {
int u = Q.front();
Q.pop();
for(int i = 0; i < (int)G[u].size(); ++i) {
int v = G[u][i];
int c = f[u][i];
dp[v] = max(dp[v], dp[u] + c);
deg[v]--;
if(!deg[v]) Q.push(v);
}
}
}
int main(){
int t; scanf("%d", &t);
while(t--) {
mst(deg, 0);
mst(dp, 0);
scanf("%d%d", &n, &m);
for(int i = 0; i <= n; ++i) {
G[i].clear();
f[i].clear();
}
for(int a, b, c, i = 0; i < m; ++i) {
scanf("%d%d%d", &a, &b, &c);
G[a].pb(b), f[a].pb(c);
deg[b]++;
}
Bfs();
int maxn = 0;
for(int i = 1; i <= n; ++i) {
maxn = max(maxn, dp[i]);
}
printf("%d\n", maxn);
}
return 0;
}