A - Zero Array Gym - 101853A
题意: 两个操作,第一个操作单点更新。第二个操作是选一个非0数,所有非0数减去这个数,问最少多少次这样的操作可以把所有数字变成0.
思路: 一开始还以为是线段树(队友bb待修改莫队),因为有单点更新,有区间相减。但是仔细理解题目,会发现一个推理的的过程 --> 不考虑0,重复的数字可以缩点,假设从小到大数字为a b c d选一个最小的数字实行一次2操作,会得到0 b - a c - a d - a。再一次忽略0选最小的数字进行2操作会得到 0 c - b d - b 。。。也就是说没进行一次而操作可以减少一种数字。那么我们只要计算除0外的数字种类就可以了。map存一下
ps:维护过程还是有点小问题的,map.size()所有开辟过内存的下标(只要访问过,不管有没有赋值),而修改过程又可能造成额外的访问,所以维护数字个数可以开一个变量而不需要用map.size();
B - New Assignment Gym - 101853B
思路: 网络流??不会
C - Intersections Gym - 101853C
题意: 相同数字连线问连线多少交点
思路: 考虑什么情况会出现交点;假设第一排数字是有序的,下面两个点下标分别为i,j.那么出现交点的条件是i < j 且a[i] > a[j],这正好是逆序对的定义。
D - Balloons Gym - 101853D
题意: 多少个非0数字
E - Maximum Sum Gym - 101853E
题意: 一个矩阵,每选一个数则相邻的数都不能选,问最大所选的数和。
思路: 状态压缩,首先枚举出每一行的所有合法状态,也就是没有相邻数字。dp[i][j]的状态定义是第i行为j状态时候的值。转移方程为 dp[i][j] = max(dp[i-1][q] + val(i,j) ,dp[i][j]);
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int state[1 << 20],dp[20][1 << 20];
int val[20][20];
int n;
int judge(int x)
{
if(x & (x << 1))
return 0;
return 1;
}
int judge2(int x,int y)
{
x = state[x];y = state[y];
if(x & (y << 1))
return 0;
if(y & (x << 1))
return 0;
if(x & y)
return 0;
return 1;
}
int getval(int i,int x)
{
int ans = 0;
x = state[x];
for(int j = 1;j <= n;j++)
{
if(x & (1 << (j - 1)))
{
ans += val[i][n - j + 1];
}
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(dp,0,sizeof(dp));
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= n;j++)
{
scanf("%d",&val[i][j]);
}
}
int cnt = 0;
for(int i = 0;i < (1 << n);i++)
{
if(judge(i))
{
state[cnt++] = i;
}
}
int ans = 0;
for(int i = 0;i < cnt;i++)
{
dp[1][state[i]] = getval(1,i);
ans = max(dp[1][state[i]],ans);
}
for(int i = 2;i <= n;i++)
{
for(int j = 0;j < cnt;j++)
{
int tmp = getval(i,j);
for(int q = 0;q < cnt;q++)
{
if(judge2(j,q))
{
dp[i][state[j]] = max(dp[i - 1][state[q]] + tmp,dp[i][state[j]]);
}
}
ans = max(dp[i][state[j]],ans);
}
}
printf("%d\n",ans);
}
}
F - Working Time Gym - 101853F
题意: 问时间差大小。
G - Hard Equation Gym - 101853G
题意: y^x=z(mod p) 求x,BSGS。貌似缺数学选手。。。以后再补吧
H - Cube Gym - 101853H I - Circles Gym - 101853I
水过~~
J - Smallest Difference Gym - 101853J
题意: 选出相差小于等于1的最大序列长度。
思路: 注意是 序列 ,而不是串,一上来就写了个单调队列,wa到怀疑人生。。
错误代码
单调队列
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 1e4 + 8;
int val[maxn];
int q_max[maxn],q_min[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int ans = 0;
for(int i = 1;i <= n;i++)
scanf("%d",&val[i]);
int h1 = 0,l1 = 0,h2 = 0,l2 = 0;
q_max[0] = q_min[0] = 0;
int last = 0;
for(int i = 1;i <= n;i++)
{
while(h1 < l1 && val[q_max[l1]] < val[i])
{
l1--;
}
q_max[++l1] = i;
while(h2 < l2 && val[q_min[l2]] > val[i])
{
l2--;
}
q_min[++l2] = i;
while(val[q_max[h1 + 1]] - val[q_min[h2 + 1]] > 1)
{
if(q_max[h1 + 1] < q_min[h2 + 1])
{
last = q_max[h1 + 1];
h1++;
}
else
{
last = q_min[h2 + 1];
h2++;
}
}
ans = max(ans,i - last);
}
printf("%d\n",ans);
}
return 0;
}
//2 8 8 9 0
纯暴力枚举
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 1e4;
int a[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
}
int x = 0,y = 0;
int ans = 0;
for(int i = 1;i <= n;i++)
{
if(a[i] - a[i - 1] == 1 && i > 1)
{
y = a[i];
x = a[i - 1];
break;
}
else if(i > 1 && a[i - 1] - a[i] == 1)
{
y = a[i - 1];
x = a[i];
break;
}
else if(a[i] == a[i - 1] && i > 1)
{
x = a[i];
y = a[i];
}
}
// printf("%d %d\n",x,y);
int num_x = 0,num_y = 0;
for(int i = 1;i <= n;i++)
{
if(a[i] == x)
{
num_x++;
}
else if(a[i] == y)
{
num_y++;
}
if(a[i] - y == 1)
{
x = y;
y = a[i];
num_x = num_y;
num_y = 0;
}
else if(x - a[i] == 1)
{
y = x;
x = a[i];
num_y = num_x;
num_x = 0;
}
ans = max(num_x + num_y,ans);
}
printf("%d\n",ans);
}
return 0;
}
AC代码
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
const int maxn = 1e4 + 7;
int a[maxn];
map<int,int>mp;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
mp.clear();
int n;
scanf("%d",&n);
int maxx = 0;
for(int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
maxx = max(maxx,a[i]);
mp[a[i]]++;
}
int ans = 0;
for(int i = 0;i < maxx;i++)
{
ans = max(ans,mp[i] + mp[i + 1]);
}
printf("%d\n",ans);
}
return 0;
}
K - Citations Gym - 101853K
题意: 字符串处理,抽出括号里的字符并输出
思路: 卡getline,得用fgets。而且注意publisher后面没有逗号,而其他的行是有逗号的吗,就是这个点卡了3h,醉了。