A
题意:n*n的网格,外框被激活。A/B两人轮流激活格子,激活一个格子的条件:四联通的位置有格子激活,四联通的位置没有同色的格子。
思路:输出n/2+1即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
int main()
{
int T;
scanf("%d",&T);
while(T)
{
T--;
int n;
scanf("%d", &n);
printf("%d\n",n/2 + 1);
}
return 0;
}
B
题意:插入/删除一些木棍,询问这些木棍是否可以组成一个正方形和一个长方形。
思路:统计每种长度有多少根+一堆特判。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#define LL long long
using namespace std;
set<int>quemax,quemin;
set<int>:: iterator it;
const int N = 1e5 + 10;
const int maxn = 1e5;
int a[N];
int main()
{
int n, x, m;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d",&x);
a[x]++;
}
for(int i = 1; i <= maxn; i++)
{
if(a[i] >= 4) quemax.insert(i);
if(a[i] >=2 &&a[i] <= 3) quemin.insert(i);
}
scanf("%d",&m);
for(int i = 1; i <= m; i++)
{
int flag = 0;
char s[10];
scanf("%s",s);
scanf("%d",&x);
if(s[0]=='+')
{
a[x]++;
if(a[x] == 2) quemin.insert(x);
if(a[x] == 4){
quemin.erase(x);
quemax.insert(x);
}
}
else
{
a[x]--;
if(a[x] == 3)
{
quemax.erase(x);
quemin.insert(x);
}
if(a[x] == 1)
{
quemin.erase(x);
}
}
if(quemax.size()>=2)
{
flag = 1;
}
else
{
if(quemax.size())
{
it = quemax.begin();
x = *it;
int t = a[x] - 4;
if(t >= 4)
flag = 1;
if(t>=2 && quemin.size()>=1)
flag = 1;
if(quemin.size()>=2)
flag = 1;
}
}
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
C
题意:构造一个排列,使得相同的数的间隔尽量大,输出最小间隔的最大值。
思路:统计出哪些数是众数,设a,b,c为众数(也可能有更多),x为其他的数,构造方法为abcxxxxxabcxxxxxabcxxxxxabc。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#define LL long long
using namespace std;
const int N = 1e5 + 10;
int a[N];
int main()
{
int T, n;
scanf("%d", &T);
while(T)
{
T--;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
a[i] = 0;
int x;
for(int i = 1; i <= n; i++)
{
scanf("%d", &x);
a[x]++;
}
int maxa = 0;
for(int i = 1; i <= n; i++)
maxa = max(maxa, a[i]);
int cnt = 0, sum = 0;
for(int i = 1; i <= n; i++)
{
if(a[i] == maxa) cnt++;
else sum +=a[i];
}
int dist = cnt - 1 + sum / (maxa - 1);
printf("%d\n",dist);
}
return 0;
}
D
题意:n*m网格,每个网格有不同的值,求同色的正方形(45度放置)的个数。
思路:将正方形切割成左右两个三角形,每个格子扫一遍,从左到右(从右到左)有单调性。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
#define LL long long
using namespace std;
const int N = 2e3 + 10;
int up[N][N], le[N][N], ri[N][N], dn[N][N], f[N][N];
char s[N][N];
int main()
{
LL ans = 0;
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
scanf("%s", s[i] + 1);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
up[i][j] = 1;
le[i][j] = 1;
if(s[i][j] == s[i - 1][j])
up[i][j] = up[i - 1][j] + 1;
if(s[i][j] == s[i][j - 1])
le[i][j] = le[i][j - 1] + 1;
}
}
for(int i = n; i > 0;i--)
{
for(int j = m; j >0; j--)
{
dn[i][j] = 1;
ri[i][j] = 1;
if(s[i][j] == s[i + 1][j])
dn[i][j] = dn[i + 1][j] + 1;
if(s[i][j] == s[i][j + 1])
ri[i][j] = ri[i][j + 1] + 1;
}
}
for(int i = 1; i <= n; i++)
{
int pre = 1;
for(int j = 1; j <= m; j++)
{
if(j - pre + 1 > le[i][j])
pre = j - le[i][j] + 1;
if(j - pre + 1 > up[i][j])
pre = j - up[i][j] + 1;
if(j - pre + 1 > dn[i][j])
pre = j - dn[i][j] + 1;
f[i][j] = j - pre + 1;
}
pre = m;
for(int j = m; j > 0; j--)
{
if(pre - j + 1 > ri[i][j])
pre = j + ri[i][j] - 1;
if(pre - j + 1 > up[i][j])
pre = j + up[i][j] - 1;
if(pre - j + 1 > dn[i][j])
pre = j + dn[i][j] - 1;
f[i][j] = min(f[i][j], pre - j + 1);
ans += f[i][j];
}
}
cout<<ans<<endl;
return 0;
}
E
题意:n个串,每个串删一个字符或者不删,求n个串能排成按照字母序升序的方案的数量。
思路:
- (串内)排序:求对于每一个串,求删除第i个字母后的串的排序。设 n x t i nxt_{i} nxti为第i个字母右侧第一个与之不同的字母的位置。从左到右扫一遍,如果 s i > s n x t i s_{i} > s_{nxt_{i}} si>snxti,放到sorted序列左边,否则放到右边。
- DP: f i , j f_{i,j} fi,j表示第i个串,删除第 s o r t e d j sorted_{j} sortedj位置的方案数。利用双指针法进行转移。
- 判断两个串的大小:hash+二分,二分第一个不同的位置,进行比较
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
const int M = 1e6 + 1;
const int N = 1e5 + 1;
const LL base = 37;
const LL mod = 1e9 + 7;
LL ff[M], h[2][M], f[2][M];
string str[N];
int nxt[2][M], sorted[2][M];
void get_sorted(int id)
{
for(int i = str[id].size() - 1; i >= 0; i--)
{
if(str[id][i] != str[id][i + 1]) nxt[id % 2][i] = i + 1;
else nxt[id % 2][i] = nxt[id % 2][i + 1];
}
h[id % 2][0] = str[id][0];
for(int i = 1; i <= str[id].size(); i++)
h[id % 2][i] = h[id % 2][i - 1] * base + str[id][i];
int l = 0;
int r = str[id].size() - 1;
for(int i = 0; i < str[id].size(); i++)
{
if(str[id][i] > str[id][nxt[id % 2][i]])
{
sorted[id % 2][l] = i;
l++;
}
else
{
sorted[id % 2][r] = i;
r--;
}
}
for(int i = str[id].size(); i > 0; i--)
{
if(sorted[id % 2][i - 1] != str[id].size() - 1)
sorted[id % 2][i] = sorted[id % 2][i - 1];
else
{
sorted[id % 2][i] = str[id].size();
break;
}
}
}
LL get_hash(int x, int cx, int pos)
{
if(pos < cx)
{
return h[x % 2][pos];
}
LL now = 0;
if(cx > 0) now = h[ x % 2][cx - 1];
now *= ff[pos + 1 - cx];
now += h[x % 2][pos + 1] - ff[pos + 1 - cx] * h[x % 2][cx];
return now;
}
char get_c(int x, int cx, int pos)
{
if(pos < cx)
return str[x][pos];
if(str[x].size() > pos + 1) return str[x][pos + 1];
return 'a' - 1;
}
int check(int x, int cx, int y, int cy)
{
int l = 0;
int r = min(str[x].size(), str[y].size()) + 1;
while(r - l > 1)
{
int mid = (l + r) >> 1;
if(get_hash(x, cx, mid - 1) != get_hash(y, cy, mid - 1))
r = mid;
else
l = mid;
}
if(get_c(x, cx, l) <= get_c(y, cy, l))
return 1;
return 0;
}
int main()
{
ff[0] = 1;
for(int i = 1; i <= 1e6; i++) ff[i] = ff[i - 1] * base;
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
cin>>str[i];
get_sorted(1);
for(int i = 0; i <= str[1].size(); i++)
f[1][i] = 1;
for(int i = 2; i <= n; i++)
{
get_sorted(i);
int k = 0;
int x = sorted[(i - 1) % 2][k];
LL sum = 0;
for(int j = 0; j <= str[i].size(); j++)
{
int y = sorted[i % 2][j];
while(k <= str[i - 1].size() && check(i - 1, x, i, y))
{
sum += f[(i - 1) % 2][k];
if(sum >= mod) sum -= mod;
k++;
x = sorted[(i - 1) % 2][k];
}
f[i % 2][j] = sum;
}
}
LL ans = 0;
for(int i = 0; i <= str[n].size(); i++)
{
ans += f[n % 2][i];
if(ans >= mod) ans -= mod;
}
cout<< ans;
return 0;
}