Problems
# | Name | ||
---|---|---|---|
A | Alexey and Train | x5859 | |
B | Napoleon Cake | x5579 | |
C | Going Home | x1506 | |
D | Two chandeliers | x95 | |
E | Matrix Sorting | x3 | |
F | Tiles for Bathroom | x1 |
这场比赛的时间就很神奇。
A Alexey and Train
模拟题
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1e5+5;
int T,n;
int a[N],b[N],tm[N];
int main()
{
// freopen("1.in","r",stdin);
int i;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
for(i=1;i<=n;i++) scanf("%d",&tm[i]);
int ans=0;
for(i=1;i<=n;i++) {
ans=ans+tm[i]+a[i]-b[i-1];
if(i==n) break;
ans=max(ans+(b[i]-a[i]+1)/2,b[i]);
}
printf("%d
",ans);
}
return 0;
}
B Napoleon Cake
差分一下就可以了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=2e5+5;
int T,n;
int a[N],c[N];
int main()
{
// freopen("1.in","r",stdin);
int i;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(i=0;i<=n;i++) c[i]=0;
for(i=1;i<=n;i++) scanf("%d",&a[i]);
for(i=1;i<=n;i++) c[max(i-a[i]+1,1)]++,c[i+1]--;
for(i=1;i<=n;i++) c[i]+=c[i-1];
for(i=1;i<=n;i++) printf("%d ",(c[i]>0));
puts("");
}
return 0;
}
C Going Home
题意,给定 (a_1...a_n) ,求出四个不同的下标满足 (x,y,z,w) 满足 (a_x+a_y=a_z+a_w)
(n le 10^5,max a le 2.5 imes 10^6) 。
很有意思的一道题。
(a_x-a_z=a_w-a_y)
刚开始我还想着用 DS 维护,发现不大行。
于是盲猜答案上界不会很大,乱证一下好像可以 (le sqrt{max a}) 。
于是暴力即可。
特判掉 出现次数 (ge 2) 的情况。
只要跑不死,就往死里跑。要死跑不完,就是 NO ANSWER。
#include<ctime>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
const int N=5e6+5;
int n,m;
int a[N],c[N];
int main()
{
// freopen("1.in","r",stdin);
int i,j;
int x;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]),m=max(m,a[i]);
for(i=1;i<=n;i++) c[a[i]]++;
vector<int> v;
for(i=1;i<=m;i++) {
if(c[i]>=4) {
puts("YES");
for(j=1,x=0;j<=n && x<4;j++)
if(a[j]==i) printf("%d ",j),x++;
return 0;
}
else if(c[i]>=2) v.push_back(i);
}
if(v.size()>=2) {
vector<int> ans;
for(i=0;i<2;i++)
for(j=1,x=0;j<=n && x<2;j++)
if(a[j]==v[i]) x++,ans.push_back(j);
swap(ans[0],ans[2]);
puts("YES");
for(i=0;i<4;i++) printf("%d ",ans[i]);
return 0;
}
for(i=1;i<=n;i++) c[a[i]]=i;
if(v.size()==1) {
for(i=1;v[0]-i>=1 && i+v[0]<=m;i++) {
if(c[v[0]-i] && c[v[0]+i]) {
puts("YES");
printf("%d %d ",c[v[0]-i],c[v[0]+i]);
for(j=1,x=0;j<=n && x<2;j++)
if(a[j]==v[0]) printf("%d ",j),x++;
return 0;
}
}
}
vector<PII> ans;
for(i=1;i<=m && clock()<=1.8*CLOCKS_PER_SEC;i++) {
ans.clear();
for(j=1;j<=n;j++) {
if(c[a[j]]==j && a[j]>i && c[a[j]-i])
ans.push_back(PII(c[a[j]-i],j));
}
sort(ans.begin(),ans.end());
if(ans.size()>=3) {
puts("YES");
vector<int> pos;
pos.push_back(ans[0].first),pos.push_back(ans[0].second);
if(ans[1].first==ans[0].second)
pos.push_back(ans[2].first),pos.push_back(ans[2].second);
else pos.push_back(ans[1].first),pos.push_back(ans[1].second);
swap(pos[0],pos[2]);
printf("%d %d %d %d
",pos[0],pos[1],pos[2],pos[3]);
return 0;
}
else if(ans.size()==2 && ans[1].first!=ans[0].second)
return printf("YES
%d %d %d %d
",ans[0].first,ans[1].second,ans[0].second,ans[1].first)&0;
}
puts("NO");
return 0;
}
D Two chandeliers
很明显的周期性质。
思路:先求出 一个周期几次 diff , 然后二分求剩下的周期。
Part 1 一个周期几次 diff
(T=lcm(n,m))
本题有一个很重要的性质,就是 (a_i) 两两不同, (b_j) 两两不同,于是相同的位置就是可枚举的。
而不同的次数就是 (T-) 相同的次数。
这里不妨假设 下标从 (0) 开始,假设 (a_i=b_j) ,则贡献的位置 (x) 满足
根据中国剩余定理,(x) 在 ([0,lcm(n,m))) 有至多一解,并且若有解,周期为 (lcm(n,m)=T)。用 excrt 合并即可。
由于对于每个 (a_i) 至多有一个 (b_j) 与之相同,并且至多有一解,故在一个周期内至多有 (min(n,m)) 个解。求出 这些解,Part 1 就做完了。
Part 2 二分求剩下的周期
不妨把 Part 1 位置存在 vector 里,则再经过 (day) 天的 diff 数就是
先 sort
一下,用 upper_bound
可以 (mathcal O(log n)) 求。
总的时间复杂度 (假设 (n,m) 同阶): (mathcal O(nlog n+log^2 n))
Code:
注意如果最后一个周期是完整的,要特判掉。
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N=1e6+5;
LL muler(LL x,LL k,LL MOD)
{
LL res=0; x=(x%MOD+MOD)%MOD; k=(k%MOD+MOD)%MOD;
while(k) {
if(k&1) res=(res+x)%MOD;
x=(x+x)%MOD; k>>=1;
}
return res%MOD;
}
LL power(LL x,LL k,LL MOD)
{
LL res=1; x%=MOD;
while(k) {
if(k&1) res=muler(res,x,MOD);
x=muler(x,x,MOD); k>>=1;
}
return res%MOD;
}
LL exgcd(LL a,LL b,LL& x,LL& y)
{
if(b==0) {
x=1; y=0;
return a;
}
LL z=exgcd(b,a%b,y,x);
y-=a/b*x;
return z;
}
LL inv(LL x,LL p)
{
LL y,z; exgcd(x,p,y,z);
return (y%p+p)%p;
}
LL excrt(int n,LL b[],LL a[])
{
LL m=a[1],ans=b[1];
for(int i=2;i<=n;i++) {
LL y,z,d=exgcd(m,a[i],y,z);
if((b[i]-ans)%d!=0) return -1;
y=muler(y,(b[i]-ans)/d,a[i]/d);
ans+=y*m;
m=a[i]/d*m;
ans=(ans%m+m)%m;
}
return ans;
}
LL gcd(LL a,LL b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
LL lcm(LL a,LL b) { return a/gcd(a,b)*b; }
int n,m;
LL kth;
int a[N],b[N],c[N];
LL A[N],B[N];
vector<LL> v;
LL calc(LL day)
{
// cerr<<day<<" "<<day-(upper_bound(v.begin(),v.end(),day)-v.begin())<<endl;
if(day<=0) return 0;
else return day-(upper_bound(v.begin(),v.end(),day)-v.begin());
}
int main()
{
// freopen("1.in","r",stdin);
int i,j;
LL x;
scanf("%d%d%lld",&n,&m,&kth);
for(i=0;i<n;i++) scanf("%d",&a[i]);
for(i=0;i<m;i++) scanf("%d",&b[i]);
memset(c,-1,sizeof c);
for(i=0;i<n;i++) c[a[i]]=i;
for(i=0;i<m;i++) {
if(~c[b[i]]) {
j=c[b[i]];
A[1]=n; A[2]=m;
B[1]=j; B[2]=i;
x=excrt(2,B,A);
if(x==-1) continue;
v.push_back(x+1);
// cerr<<x<<endl;
}
}
sort(v.begin(),v.end());
LL times=lcm(n,m)-v.size();
LL turns=(kth-1)/times;
kth-=turns*times;
LL L=-1,R=lcm(n,m),mid;
while(L+1<R) {
mid=(L+R)>>1;
if(calc(mid)>=kth) R=mid;
else L=mid;
}
printf("%lld
",turns*lcm(n,m)+R);
return 0;
}
E,F 不会 wtcl:)