B. Squares and Cubes
import sys
DEBUG = 0
if DEBUG==1:
sys.stdin = open('B-1.in', 'r')
#sys.stdout = open('tmp.out', 'w')
def readi():
return [int(t) for t in input().split()]
def solve(n):
ans = 0
i = 1
a = {}
while True: // 将找到的平方数放到set中
t = i*i
if t<=n:
a[t]=1
ans += 1
else:
break
i += 1
i=1
while True:
t = i**3
if t<=n:
if not(t in a):
ans += 1
else:
break
i += 1
print(ans)
def main():
T, = readi()
for i in range(T):
n, = readi()
solve(n)
main()
C. Wrong Addition
import sys
DEBUG = 0
if DEBUG==1:
sys.stdin = open('C-1.in', 'r')
#sys.stdout = open('tmp.out', 'w')
def readi():
return [int(t) for t in input().split()]
def solve(a,b):
ans = ''
while len(a)>0 and len(b)>0:
x=a[-1]
a.pop(-1)
if len(a)>0 and x<b[-1]: // 使用if,不能使用while,这会导致计算多个0与x相减
x = a[-1]*10+x
a.pop(-1)
t = x-b[-1]
if t>=10 or t<0:
print(-1)
return
ans = str(t) + ans
b.pop(-1)
if len(a)<len(b):
print(-1)
else:
while len(a)>0:
ans = str(a[-1])+ans
a.pop(-1)
print(int(ans))
def main():
T, = readi()
for i in range(T):
a,b = readi()
a=list(str(a))
b=list(str(b))
for i in range(len(a)):
a[i]=int(a[i])
for i in range(len(b)):
b[i]=int(b[i])
solve(b,a)
main()
D. New Year's Problem
import sys
DEBUG = 0
if DEBUG==1:
sys.stdin = open('D-1.in', 'r')
#sys.stdout = open('tmp.out', 'w')
def readi():
return [int(t) for t in input().split()]
def check(m,n,a,k):#检查能否使最小的欢乐度大于等于k同时
S = {}
p = 0 #得到礼物的人数
q = 0 #使用的商店数量
for i in range(n):
b = []
for j in range(m):
if a[j][i] >= k:
b.append(j)
if len(b)>0:
found = False
for j in range(len(b)): #尽可能使用尽量少的商店
if b[j] in S:
found = True
S[b[j]]=1
if found:
pass
else:
q += 1
p += 1
if p==n and q<=n-1: #满足最小欢乐度大于等于k的人数为n,且使用的商店数小于等于n-1
return True
else:
return False
def solve(m,n,a):
lo,hi = 1,1000000000
ans=0
while lo<=hi:
mid=(lo+hi)//2
if check(m,n,a,mid):
ans=mid
lo=mid+1
else:
hi=mid-1
print(ans)
def main():
T, = readi()
for i in range(T):
input()
m,n = readi()
a = []
for i in range(m):
a.append(readi())
solve(m,n,a)
main()
E.MEX and Increments
题意:给定一个数列a,每次可以任选一个数将它加一。定义MEX(i)为使数列中第一个未出现的数是i,最少需要对数列操作几次?i从0到n,每次都相当于重新操作数列。
题解:使用cnt(i)记录i的出现次数。考虑求MEX(i)时如果i-1没有出现的情况。
如果i-1没有出现,那么需要从小于i-1的元素中取一个补为i-1,来保证0到i-1都存在。
于是我们可以在每计算完一个MEX后,把当前多余的元素放到一个队列里,表示这个元素可以用于后续补充为另一个元素。使用acc累加操作次数,当计算MEX(i)时,需要通过acc次操作使0到i-1都出现,通过cnt[i]次操作使现有的i变为i+1,这样就可以保证只有i没有出现。
import sys
from heapq import *
DEBUG = 1
if DEBUG==1:
sys.stdin = open('E-1.in', 'r')
#sys.stdout = open('tmp.out', 'w')
def readi():
return [int(t) for t in input().split()]
def solve(n,a):
cnt = [0]*(n+1)
q = []
for i in range(n):
cnt[a[i]]+=1
acc = 0 #对于MEX(i)把前面元素补全为0到i-1的总代价
ans = [-1] * (n+1)
for i in range(n+1):
if i==0:
ans[i] = cnt[i]
for j in range(cnt[i]-1):
q.append(i)
else:
if cnt[i-1]==0:
if len(q)>0:
acc += ((i-1) - q[-1]) #把q中最后一个元素补为i-1
q.pop(-1)
else: #剩下的值无解
return ans
ans[i] = acc + cnt[i] # cnt[i]:把全部i补为i+1
for j in range(cnt[i]-1): #把cnt[i]-1个元素加入到队列中让它们可以补后面的元素
q.append(i)
return ans
def main():
T, = readi()
for i in range(T):
n, = readi()
a = readi()
ans = solve(n,a)
print(*ans)
main()
G. Unusual Minesweeper
解:使用map维护横坐标或纵坐标相同的一组雷。对于横坐标相同的每组雷,按照y坐标排序之后就可以将y坐标之差小于等于k的雷通过并查集合并到一起。使用并查集维护一组连环引爆的雷的最小起爆时间。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#include<limits.h>
#include<assert.h>
using namespace std;
#define all(X) (X).begin(), (X).end()
#define rep(I,A,B) for(int I=(A);I<(B);I++)
#define repd(I,A,B) for(int I=(A);I>(B);I--)
#define sort_unique(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define mp make_pair
#define ms0(X) memset((X), 0, sizeof((X)))
#define ms1(X) memset((X), -1, sizeof((X)))
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef vector<int> VI;
typedef vector<PII> VPII;
typedef vector<LL> VLL;
typedef vector<PLL> VPLL;
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(int64_t &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &&head, U &&... tail) { _R(head); R(tail...); }
template<class T> void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const int64_t &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template<class T,class U> void _W(const pair<T,U> &x) {_W(x.first); putchar(' '); _W(x.second);}
template<class T> void _W(const vector<T> &x) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
void W() { }
template<class T, class... U> void W(const T &head, const U &... tail) { _W(head); putchar(sizeof...(tail) ? ' ' : '\n'); W(tail...); }
#define DEBUG 0
#define MAXN 200000
struct V3 {
int x,y,t;
};
int T,n,k;
V3 a[MAXN];
bool cmpx(int i,int j) {
return a[i].x<a[j].x;
}bool cmpy(int i,int j) {
return a[i].y<a[j].y;
}
struct DSU {
int *fa,*mint; // 一组雷中的最小起爆时间
DSU(int n, V3 a[MAXN]) {
fa=new int[n];
mint=new int[n];
rep(i,0,n) {
fa[i]=i;
mint[i]=a[i].t;
}
}
int find(int v) { return (fa[v]==v) ? v : fa[v]=find(fa[v]); }
void unite(int u, int v) {
mint[find(v)]=min(mint[find(u)],mint[find(v)]);
fa[find(u)] = find(v);
}
};
void solve(int n, int k, V3 a[MAXN]) {
DSU dsu = DSU(n,a);
map<int,VI> mpx,mpy;
rep(i,0,n) {
mpx[a[i].x].push_back(i);
mpy[a[i].y].push_back(i);
}
for(auto kvp:mpx) {
sort(all(kvp.second),cmpy);
VI &v = kvp.second;
rep(i,0,v.size()-1)
if(a[v[i+1]].y - a[v[i]].y <= k)
dsu.unite(v[i],v[i+1]);
}
for(auto kvp:mpy) {
sort(all(kvp.second),cmpx);
VI &v = kvp.second;
rep(i,0,v.size()-1)
if(a[v[i+1]].x - a[v[i]].x <= k)
dsu.unite(v[i],v[i+1]);
}
VI b; // 收集每组雷中最短起爆时间
static int inb[MAXN];
ms0(inb);
rep(i,0,n) {
if(!inb[dsu.find(i)]) {
inb[dsu.find(i)]=1;
b.push_back(dsu.mint[dsu.find(i)]);
}
}
sort(all(b));
int ans=b.size()-1; //默认手动引爆所有雷花费的时间
rep(i,0,b.size()) //计算第0到i个雷自动引爆从第i+1个雷开始手动引爆花费的时间
ans=min(ans,max(b[i],(int)b.size()-i-2)) ;
W(ans);
}
int main()
{
#if DEBUG
freopen("tmp.in","r",stdin);
//freopen("tmp.out","w",stdout);
#endif
R(T);
rep(_,0,T) {
R(n,k);
rep(i,0,n)
R(a[i].x,a[i].y,a[i].t);
solve(n,k,a);
}
return 0;
}