入口
很少打这个比赛
A - We Love Golf
签到
#include<bits/stdc++.h>
using namespace std;
int main()
{
int k,a,b;
cin>>k>>a>>b;
for(int i=a;i<=b;i++) {
if(i%k==0) {
puts("OK");
return 0;
}
}
puts("NG");
return 0;
}
B - 1%
有点奇葩细节,每年的利息结余后几毛的零头不要了(QAQ~
AC code:
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
int main()
{
ULL k;
cin>>k;
ULL ans = 100;
for(int i=1;i<=1e6;i++){
ans = ans * 1.01;
if(ans>=k){
printf("%d\n",i);
break;
}
}
return 0;
}
D - Floor Function
先放D,感觉比C简单,,莽一发就过了。
AC code:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
LL a,b,n;
cin>>a>>b>>n;
cout<<a*min(b-1,n)/b<<endl;
return 0;
}
C - Many Requirements (递归枚举)
一开始想着二进制枚举要选的Q数列,后来发现a数组非递减,且a数组长度 2≤N≤10,元素大小1≤M≤10,那就直接枚举a数组(远小于全排),然后check取最大值就可以了。
AC code:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
struct node{
int a,b,c,d;
}Q[55];
int n,m,q;
int s[15],ans;
void check()
{
int num=0;
for(int i=0;i<q;i++){
if(s[Q[i].b]-s[Q[i].a]==Q[i].c) num+=Q[i].d;
}
ans = max(ans,num);
}
void dfs(int pos,int val)
{
s[pos] = val;
if(pos==n) {
check();return ;
}
for(int i=val;i<=m;i++){
dfs(pos+1,i);
}
}
int main()
{
cin>>n>>m>>q;
for(int i=0;i<q;i++){
int a,b,c,d;
cin>>a>>b>>c>>d;
Q[i] = (node){a,b,c,d};
}
dfs(1,1);
cout<<ans<<endl;
return 0;
}
E - Rotation Matching (构造)
这个题有点意思。首先最多构造(N-1)/2 对儿比赛,样例的构造方式是个错误的引导,因为如果你按照样例的策略 (下图),那么在第三个回合时就会有重复的两个人比赛。由此可见,构造时必须要严格确保两个数的距离不能变,比如 3 和 8 的距离就不会变,因为3前边和8后边的数(1 2 9 10) 的个数是大于等于3和8之间的数的个数的。所以我们可以把1~N的数分成两半,再按照下面构造就没问题了。
AC code:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
int num=0;
if(n%2==0) n--; //可以都转变成奇数构造,因为m <= (n-1)/2;
for(int i=1;i<=n/4&&num<m;i++){ //前一半
cout<<i<<" "<<n/2-i+1<<"\n";
num++;
}
for(int i=n/2+1,j=0;num<m;i++,j++){ //后一半,题目保证m是合法的,所以可以直接num < m
cout<<i<<" "<<n-j<<"\n";
num++;
}
return 0;
}
F - LIS on Tree (树上LIS)
就是求树上每条链的最长上升子序列 LIS,那就直接dfs的时候动态用二分的方法O(nlogn)求LIS就可以了,但是记得回溯时恢复数据;
AC code:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
int h[N],e[N*2],ne[N*2],idx;
int w[N];
int ans[N];
int low[N];
void add(int a,int b){
e[idx] = b,ne[idx] = h[a] , h[a] = idx++;
}
void dfs(int s,int fa,int pos)
{
int temp1=-1,temp2=0,k=0;
if(low[pos] < w[s]) temp1 = low[pos+1] ,low[++pos] = w[s]; //做好记录
else {
int j = lower_bound(low+1,low+pos+1,w[s]) - low ;
temp2 = low[j],k = j;
low[j] = w[s];
}
ans[s] = pos;
for(int i=h[s];~i;i=ne[i]){
int j = e[i];
if(j==fa) continue;
dfs(j,s,pos);
}
if(temp1!=-1) low[pos] = temp1; //回溯
else low[k] = temp2;
}
int main()
{
int n,a,b;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
memset(h,-1,sizeof h);
for(int i=1;i<n;i++){
scanf("%d%d",&a,&b);
add(a,b),add(b,a);
}
dfs(1,0,0);
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}
下面时原始没有优化的代码,一组数据 T 了,其他都AC了。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
int h[N],e[N*2],ne[N*2],idx;
int w[N],in[N];
int arr[N],ele[N],st[N];
int low[N];
void add(int a,int b){
e[idx] = b,ne[idx] = h[a] , h[a] = idx++;
}
void fun(int n)
{
int ans=1;
low[ans] = arr[1];
ele[1] = 1;
for(int i=2;i<=n;i++){
if(low[ans] < arr[i]) low[++ans] = arr[i];
else {
int j = lower_bound(low+1,low+ans+1,arr[i]) - low ;
low[j] = arr[i];
}
ele[st[i]] = ans;
}
}
void dfs(int s,int fa,int cnt)
{
if(in[s]==1&&s!=1){
fun(cnt);return;
}
for(int i=h[s];~i;i=ne[i]){
int j = e[i];
if(j==fa) continue;
arr[++cnt] = w[j];
st[cnt] = j;
dfs(j,s,cnt);
--cnt; //回溯时恢复数据
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
memset(h,-1,sizeof h);
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
add(a,b),add(b,a);
in[a]++,in[b]++;
}
arr[1] = w[1];
st[1] = 1;
dfs(1,0,1);
for(int i=1;i<=n;i++) printf("%d\n",ele[i]);
return 0;
}