Preface
这场由于下午四点约好了和祁神打乒乓球,因此两点开了一场VP,结果困得要死D题一个特判写挂了没看出来调了贼久
然后E题秒出正解,但因为一个极其傻逼的地方挂了又没调出来,鉴定为纯纯的飞舞
A. Guess the Maximum
签到,每次选的一定是相邻的两个
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=50005;
int t,n,a[N];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (scanf("%d",&t);t;--t)
{
RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]);
int ans=max(a[1],a[2]); for (i=2;i<n;++i) ans=min(ans,max(a[i],a[i+1]));
printf("%d\n",ans-1);
}
return 0;
}
B. XOR Sequences
手玩一下发现其实就是找 \(x,y\) 从低到高第一个不一样的位 \(h\),答案就是 \(2^h\)
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
int t,x,y;
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (scanf("%d",&t);t;--t)
{
RI i; scanf("%d%d",&x,&y);
for (i=0;i<30;++i) if (((x>>i)&1)!=((y>>i)&1))
{
printf("%d\n",(1<<i)); break;
}
}
return 0;
}
C. Earning on Bets
根据人类直觉不难发现让所有的 \(k_i\times a_i\) 都相等是最优的策略,如果这样都不合法说明 \(\sum \frac{1}{k_i}>1\),此时不管怎么安排肯定都是无解的
构造答案的话令所有的 \(k_i\times a_i\) 都等于 \(\operatorname{lcm}(k_i)\) 即可
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=55;
int t,n,a[N],b[N];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (scanf("%d",&t);t;--t)
{
RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]);
LL g=a[1]; for (i=2;i<=n;++i) g=g/__gcd(g,1LL*a[i])*a[i];
LL sum=0; for (i=1;i<=n;++i) sum+=g/a[i];
if (sum>=g) puts("-1"); else
{
for (i=1;i<=n;++i) printf("%d%c",g/a[i]," \n"[i==n]);
}
}
return 0;
}
D. Fixing a Binary String
考虑枚举操作的前缀长度 \(p\) ,判断操作后是否合法需要满足哪些要求
首先此时序列的开头变成了 \(p+1\),因此首先需要判断 \([p+1,n]\) 这一段能否作为一段合法的开头
然后就是要把 \([1,p]\) 这段翻转后接到后面去,就需要判断 \([p:1]\) 这一段能否作为一段合法的后缀
与此同时中间接合处的情况还需要讨论一下:
- 若 \(k\mid p\),此时需要满足 \(s_p\ne s_n\),因为这种情况下 \(s_p\) 和 \(s_n\) 分属于不同的块;
- 若 \(k\nmid p\),此时需要满足 \(s_p=s_n\),因为这种情况下 \(s_p\) 和 \(s_n\) 分属于同一个块;
前后缀的合法情况很容易写出递推的预处理式子,总复杂度 \(O(n)\)
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=100005;
int t,n,k,pre[N],suf[N],pfx[N]; char s[N];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (scanf("%d",&t);t;--t)
{
RI i,j; scanf("%d%d%s",&n,&k,s+1);
auto check=[&](void)
{
for (RI i=2;i<=k;++i) if (s[i]!=s[1]) return 0;
for (RI i=1;i<=n-k;++i) if (s[i]==s[i+k]) return 0;
return 1;
};
if (check()) { printf("%d\n",n); continue; }
for (i=1;i<=n;++i) pfx[i]=pfx[i-1]+(s[i]-'0');
auto same=[&](CI l,CI r)
{
int tmp=pfx[r]-pfx[l-1];
return tmp==0||tmp==r-l+1;
};
for (i=1;i<=k;++i) pre[i]=same(1,i);
for (i=2;i<=n/k;++i)
{
for (j=(i-1)*k+1;j<=i*k;++j)
pre[j]=(pre[(i-1)*k]&&same((i-1)*k+1,j)&&s[(i-1)*k]!=s[j]);
}
for (i=n;i>=n-k+1;--i) suf[i]=same(i,n);
for (i=n-k;i>=1;--i) suf[i]=(same(i,i+k-1)&&suf[i+k]&&s[i]!=s[i+k]);
//for (i=1;i<=n;++i) printf("%d%c",pre[i]," \n"[i==n]);
//for (i=1;i<=n;++i) printf("%d%c",suf[i]," \n"[i==n]);
bool flag=0; for (i=1;i<n;++i)
if (pre[i]&&suf[i+1])
{
if ((i%k!=0&&s[i]==s[n])||(i%k==0&&s[i]!=s[n]))
{
printf("%d\n",i); flag=1; break;
}
}
if (!flag) puts("-1");
}
return 0;
}
E. Manhattan Triangle
刚好打这场的前一天和队友聊到了曼哈顿距离转切比雪夫距离的trick,然后这个题就可以直接套
进行 \((x,y)\to (x+y,x-y)\) 的变换后,要找的三个点两两间切比雪夫距离均为 \(d\)
显然此时三个点的距离不能都在横坐标或者纵坐标上体现,因此分析后可以得到这三个点必为以下两种情况之一:
- 两点横坐标均为 \(x\),纵坐标 \(|y_1-y_2|=d\),此时第三个点横坐标为 \(x\pm d\),纵坐标 \(\in[y_1,y_2]\);
- 两点纵坐标均为 \(y\),横坐标 \(|x_1-x_2|=d\),此时第三个点纵坐标为 \(y\pm d\),横坐标 \(\in[x_1,x_2]\);
以前者为例,我们把所有横坐标相同的点存入一个 vector
中
枚举确定公共的 \(x\) 的值,用 two pointers
找出纵坐标之差符合要求的点对,然后在 \(x\pm d\) 对应的 vector
里二分找符合要求的点即可
后者只需要把横纵坐标交换后再做一遍即可,总复杂度 \(O(n\log n)\)
#include<cstdio>
#include<iostream>
#include<utility>
#include<vector>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<set>
#include<array>
#include<random>
#include<bitset>
#include<ctime>
#include<limits.h>
#include<assert.h>
#include<unordered_set>
#include<unordered_map>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
#define Tp template <typename T>
using namespace std;
typedef long long LL;
typedef long double LDB;
typedef unsigned long long u64;
typedef pair <int,int> pi;
typedef vector <int> VI;
typedef array <int,3> tri;
const int N=200005,S=600000;
int t,n,d,x[N],y[N]; vector <pi> p[2*S+5];
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
for (scanf("%d",&t);t;--t)
{
RI i; for (scanf("%d%d",&n,&d),i=1;i<=n;++i)
{
int a,b; scanf("%d%d",&a,&b);
x[i]=a+b; y[i]=a-b;
}
auto solve=[&](void)
{
RI i,j; vector <int> X;
for (i=1;i<=n;++i)
{
p[x[i]+S].push_back(pi(y[i],i));
X.push_back(x[i]+S);
}
sort(X.begin(),X.end());
X.erase(unique(X.begin(),X.end()),X.end());
auto clear=[&](void)
{
for (auto x:X) p[x].clear();
};
for (auto x:X) sort(p[x].begin(),p[x].end());
for (auto x:X)
{
for (j=0,i=1;i<p[x].size();++i)
{
while (p[x][i].fi-p[x][j].fi>d) ++j;
int y_1=p[x][j].fi,y_2=p[x][i].fi;
if (y_2-y_1!=d) continue;
auto find=[&](vector <pi>& vec,CI y_1,CI y_2)
{
auto it=lower_bound(vec.begin(),vec.end(),pi(y_1,0));
if (it==vec.end()||it->fi>y_2) return pi(-1,-1);
return *it;
};
pi tmp=find(p[x-d],y_1,y_2);
if (tmp.se!=-1)
{
printf("%d %d %d\n",p[x][i].se,p[x][j].se,tmp.se);
clear(); return 1;
}
tmp=find(p[x+d],y_1,y_2);
if (tmp.se!=-1)
{
printf("%d %d %d\n",p[x][i].se,p[x][j].se,tmp.se);
clear(); return 1;
}
}
}
clear(); return 0;
};
if (solve()) continue;
for (i=1;i<=n;++i) swap(x[i],y[i]);
if (solve()) continue;
puts("0 0 0");
}
return 0;
}
Postscript
这场F题感觉挺难的,想了下不太会做索性直接开摆
标签:typedef,951,Codeforces,long,int,Div,include,se,define From: https://www.cnblogs.com/cjjsb/p/18287639