版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenzhenyu123456/article/details/53095975
A
充要条件:
如果
可以到达
点,那么一定有一条
直达
的有向边。
预处理闭包,然后
一下就好。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
typedef long long LL;
const int MAXN = 2016 + 100;
const int MOD = 1e9 + 7;
char str[MAXN][MAXN];
bool Map[MAXN][MAXN];
vector<int> P[MAXN], Q[MAXN];
bool vis[MAXN];
void BFSP(int s) {
queue<int> Q; Q.push(s); vis[s] = true;
while(!Q.empty()) {
int u = Q.front(); Q.pop();
for(int i = 0; i < P[u].size(); i++) {
int v = P[u][i];
if(!vis[v]) {
vis[v] = true;
Map[s][v] = true;
Q.push(v);
}
}
}
}
void BFSQ(int s) {
queue<int> q; q.push(s); vis[s] = true;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = 0; i < Q[u].size(); i++) {
int v = Q[u][i];
if(!vis[v]) {
vis[v] = true;
Map[s][v] = true;
q.push(v);
}
}
}
}
int main()
{
int t; scanf("%d", &t);
while(t--) {
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++) {
P[i].clear(); Q[i].clear();
for(int j = 1; j <= n; j++) {
Map[i][j] = false;
}
}
for(int i = 1; i <= n; i++) {
scanf("%s", str[i] + 1);
for(int j = 1; j <= n; j++) {
if(str[i][j] == 'P') {
P[i].push_back(j);
}
else if(str[i][j] == 'Q') {
Q[i].push_back(j);
}
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) vis[j] = false;
BFSP(i);
}
bool flag = true;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(Map[i][j]) {
if(str[i][j] != 'P') {
flag = false; break;
}
}
Map[i][j] = false;
}
if(!flag) {
break;
}
}
if(!flag) {
printf("N\n");
continue;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) vis[j] = false;
BFSQ(i);
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(Map[i][j]) {
if(str[i][j] != 'Q') {
flag = false; break;
}
}
Map[i][j] = false;
}
if(!flag) {
break;
}
}
printf(flag ? "T\n" : "N\n");
}
return 0;
}
C
像这样的题目肯定是套路。多推几次,也就找到套路了。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 4e4 + 10;
const int MOD = 1e9 + 7;
map<pii, bool> fp;
int num[MAXN];
int main()
{
int t; scanf("%d", &t);
while(t--) {
int n, m; scanf("%d%d", &n, &m);
fp.clear();
for(int i = 1; i <= n; i++) num[i] = 0;
for(int i = 1; i <= n - 1; i++) {
int u, v, w; scanf("%d%d%d", &u, &v, &w);
if(w == 1) {
num[u]++; num[v]++;
if(u > v) {
swap(u, v);
}
fp[pii(u, v)] = true;
}
}
while(m--) {
int op, x, y, z;
scanf("%d", &op);
if(op == 0) {
scanf("%d", &x);
printf(num[x] & 1 ? "Girls win!\n" : "Boys win!\n");
}
else {
scanf("%d%d%d", &x, &y, &z);
if(x > y) {
swap(x, y);
}
bool flag = fp[pii(x, y)];
if(z == 1) {
if(!flag) {
num[x]++; num[y]++;
fp[pii(x, y)] = true;
}
}
else {
if(flag) {
num[x]--; num[y]--;
fp[pii(x, y)] = false;
}
}
}
}
}
return 0;
}
E
表示处理到第
列,第
列的状态是
,且第
列的地雷个数是
。枚举第
列的状态,暴力转移即可。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
const int MAXN = 1e4 + 10;
const int MOD = 1e8 + 7;
void add(int &x, int y) { x += y; if(x >= MOD) x -= MOD; }
char str[MAXN];
int dp[MAXN][4][3];
int Snum[4] = {0, 1, 1, 2};
int num[MAXN];
int main()
{
int t; scanf("%d", &t);
while(t--) {
scanf("%s", str + 1);
int len = strlen(str + 1);
for(int i = 1; i <= len; i++) {
num[i] = str[i] - '0';
}
memset(dp, 0, sizeof(dp));
for(int i = 0; i < 4; i++) {
for(int j = 0; j <= min(num[1], 2); j++) {
if(Snum[i] + j == num[1]) {
dp[1][i][j] = 1;
}
}
}
for(int i = 2; i <= len; i++) {
for(int j = 0; j < 4; j++) {
if(Snum[j] > num[i]) continue;
for(int k = 0; k < 4; k++) {
int have = num[i] - Snum[j] - Snum[k];
if(have >= 0 && have <= 2) {
add(dp[i][j][have], dp[i - 1][k][Snum[j]]);
}
}
}
}
int ans = 0;
for(int i = 0; i < 4; i++) {
add(ans, dp[len][i][0]);
}
printf("%d\n", ans);
}
return 0;
}
预处理去重,每次二分
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 100 + 10;
struct Node {
int val, pos;
};
Node num[MAXN][MAXN], rec[MAXN];
int cnt[MAXN];
bool cmp(Node a, Node b) {
return a.val != b.val ? a.val < b.val : a.pos > b.pos;
}
int a[MAXN], sum[MAXN];
int main()
{
int t; scanf("%d", &t);
while(t--) {
int n; scanf("%d", &n); sum[0] = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum[i] = sum[i - 1] ^ a[i];
}
for(int i = 1; i <= n; i++) {
cnt[i] = 0;
for(int j = i; j <= n; j++) {
rec[cnt[i]].pos = j;
rec[cnt[i]].val = sum[j] ^ sum[i - 1];
cnt[i]++;
}
sort(rec, rec + cnt[i], cmp);
int top = cnt[i]; cnt[i] = 1;
num[i][0] = rec[0];
for(int j = 1; j < top; j++) {
if(rec[j].val != rec[j - 1].val) {
num[i][cnt[i]] = rec[j];
cnt[i]++;
}
}
}
int m; scanf("%d", &m);
while(m--) {
int x; scanf("%d", &x);
int ans = 100000, len = 0;
for(int i = 1; i <= n; i++) {
if(num[i][cnt[i] - 1].val < x) {
int V = abs(num[i][cnt[i] - 1].val - x);
int L = num[i][cnt[i] - 1].pos - i + 1;
if(V < ans || (V == ans && L > len)) {
ans = V; len = L;
}
}
else {
int l = 0, r = cnt[i] - 1;
int P;
while(r >= l) {
int mid = l + r >> 1;
if(num[i][mid].val >= x) {
P = mid;
r = mid - 1;
}
else {
l = mid + 1;
}
}
int V, L;
if(P > 0) {
V = abs(num[i][P - 1].val - x);
L = num[i][P - 1].pos - i + 1;
if(V < ans || (V == ans && L > len)) {
ans = V; len = L;
}
}
V = abs(num[i][P].val - x);
L = num[i][P].pos - i + 1;
if(V < ans || (V == ans && L > len)) {
ans = V; len = L;
}
}
}
printf("%d\n", len);
}
printf("\n");
}
return 0;
}
I
贪心,维护一个可能出现的最小值
,最大值
。
每次
区间
和区间
是否相交。
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;
LL f[62];
int main()
{
f[0] = 1;
for(int i = 1; i <= 61; i++) {
f[i] = f[i - 1] * 2;
}
int T; scanf("%d", &T);
while(T--) {
LL l, r; scanf("%lld%lld", &l, &r);
if(l == 0 && l == r) {
printf("0\n");
continue;
}
if(l == 0) l++;
LL ans = r;
LL Min = 0, Max = 0;
int pos = -1;
for(int i = 61; i >= 0; i--) {
if(r & f[i]) {
pos = i;
}
else {
if(pos == -1) continue;
Max = r - f[pos] + Min;
for(int j = pos - 1; j >= 0; j--) {
if(r & f[j]) {
}
else {
Max += f[j];
}
}
if(Min + f[i] >= r + 1 || Max <= l - 1) {
continue;
}
ans += f[i];
Min += f[i];
}
}
printf("%lld\n", ans);
}
return 0;
}