目录
A | B | C | D | E | F |
---|---|---|---|---|---|
√ | √ | √ | √ | √ | ○ |
( √:做出; ●:尝试未做出; ○:已补题 )
题目地址:https://atcoder.jp/contests/abc177
A Don’t be late
题意:水题
思路:
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
int x=0,flag=1; char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
int main()
{
int d=read(),t=read(),s=read();
puts(s*t>=d?"Yes":"No");
return 0;
}
B Substring
题意:水题
思路:
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
int x=0,flag=1; char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
char s[1005],t[1005];
int main()
{
scanf("%s %s",s+1,t+1);
int ns=strlen(s+1),nt=strlen(t+1);
int ans=1e9;
for(int i=1;i+nt-1<=ns;i++)
{
int cnt=0;
for(int j=i,k=1;k<=nt;k++,j++)
if(s[j]!=t[k])
cnt++;
ans=min(ans,cnt);
}
cout<<ans;
return 0;
}
C Sum of product of pairs
题意:水题
思路:计算一个后缀和就行了
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
int x=0,flag=1; char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
const LL M=1e9+7;
const int maxn=2e5+5;
LL A[maxn];
int main()
{
int n=read();
REP(i,1,n) A[i]=A[i-1]+read();
LL ans=0;
for(int i=1;i<n;i++)
{
ans=(ans+(A[n]-A[i])%M*(A[i]-A[i-1]))%M;
}
cout<<ans;
return 0;
}
D Friends
题意:并查集水题。
思路:算完并查集之后找到最大的那一个集合,输出集合大小即可。
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
int x=0,flag=1; char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
const int maxn=2e5+5;
int far[maxn],t[maxn];
int findd(int x){return x==far[x]?x:far[x]=findd(far[x]);}
void unite(int x,int y){far[findd(x)]=findd(y);}
int main()
{
int n=read(),m=read();
REP(i,1,n) far[i]=i;
while(m--)
{
int a=read(),b=read();
unite(a,b);
}
REP(i,1,n) t[findd(i)]++;
cout<<*max_element(t+1,t+n+1);
return 0;
}
E Coprime
题意:给你 N( 2 ≤ N ≤ 1 0 6 2\le N \le 10^6 2≤N≤106) 个数字(数字大小不超过 1 0 6 10^6 106),有三种可能性:
- 这 N 个数字两两互质;
- 这 N 个数字总体的最大公因数等于 1;
- 其它情况
现在你需要判断是哪种情况。
思路:数据量非常大,肯定不能暴力。注意到数字大小限制,如果两个数字不互质,那么它们一定有共同的质因子,而 1000000 以内的质因数不会特别多,根据抽屉原理,如果数据量很大的时候,我们很快就能找到两个不互质的数。所以对于第一种情况,做法就是对每个数分解质因数,然后统计哪些质因数出现过,然后标记出来,如果之前这个质因数已经出现过,那么就可以排除第一种情况了。
对于第二种情况那就非常简单,直接扫一遍计算即可。
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
int x=0,flag=1; char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
const int maxn=1e6+5;
bool isprime[maxn];
int prime[maxn],cnt,a[maxn],n;
bool pairwise()
{
set<int> t;
REP(i,1,n)
{
int x=a[i];
for(int j=1;prime[j]*prime[j]<=x;j++)
if(x%prime[j]==0)
{
if(t.count(prime[j])) return 0;
t.insert(prime[j]);
while(x%prime[j]==0) x/=prime[j];
}
if(x>1)
{
if(t.count(x)) return 0;
t.insert(x);
}
}
return 1;
}
bool setwise()
{
int x=a[1];
REP(i,2,n) x=__gcd(x,a[i]);
return x==1;
}
int main()
{
REP(i,2,1000000) isprime[i]=1;
for(int i=2;i<=10000;i++)
if(isprime[i])
for(int j=i*i;j<=1000000;j+=i)
isprime[j]=0;
for(int i=2;i<=1000000;i++)
if(isprime[i])
prime[++cnt]=i;
n=read();
REP(i,1,n) a[i]=read();
if(pairwise()) puts("pairwise coprime");
else if(setwise()) puts("setwise coprime");
else puts("not coprime");
return 0;
}
F I hate Shortest Path Problem
题意:一个 (H+1)*W( 1 ≤ H , W ≤ 2 × 1 0 5 1\le H,W\le 2\times10^5 1≤H,W≤2×105) 的网格,只用考虑上面 H*W 的部分,如果某个格子没有挡板,那么它可以往下或者往右走,如果有挡板,那么只能往右走。现在对于每一行,给出 A i A_i Ai 和 B i B_i Bi ,表示 [ A i , B i ] [A_i,B_i] [Ai,Bi] 这个区间内的格子有挡板,然后你需要回答的问题是:对于每一个 i ∈ [ 1 , H ] i\in [1,H] i∈[1,H] ,如果理性的选择第一行的起始位置,最少要经过多少步,才可以到达第 i + 1 i+1 i+1 行的任意一个位置?如果不可能到达,则输出 -1 。
思路:对于这种复杂问题肯定是要想办法一点一点分析的。我们用一个数组表示在某次处理中,每个位置的最优解,然后首先考虑对于有挡板的这些格子,可以把它们都 +inf,因为它们不能往下走,所以它们下面那些点一定没有左边的点更优(因为就算可以也是要从左边那些走过来),所以直接 +inf 对答案没有影响;然后有一个点要特殊考虑,就是 B i + 1 B_i+1 Bi+1 那个点,它可以从 [ 1 , B i ] [1,B_i] [1,Bi] 中的某个最优点转移过来,但是只用考虑这个最优点,因为它右边的点通过这种方法转移的话,一定没有它更优;然后剩下的就是所有点 +1,代表往下走一格。
然后考虑如何维护那个特殊点的处理(其他两种线段树很好解决),维护方法就是再建一个线段树,维护 a n s i − i ans_i-i ansi−i 的值,因为处理特殊点的时候,转移要考虑距离,所以维护这个线段树的话,取其中的最小值 m i n x minx minx,每次就可以拿 m i n x + r minx+r minx+r(代入后就是 a n s i + r − i ans_i+r-i ansi+r−i)去和 a n s r ans_r ansr 比较看是否需要更新。
代码:
#define DIN freopen("input.txt","r",stdin);
#define DOUT freopen("output.txt","w",stdout);
#include <bits/stdc++.h>
#include <cstdio>
#define mem(a,b) memset(a,b,sizeof(a))
#define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
#define REP_(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
using namespace std;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::pair<int,int> P;
int read()
{
int x=0,flag=1; char c=getchar();
while((c>'9' || c<'0') && c!='-') c=getchar();
if(c=='-') flag=0,c=getchar();
while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return flag?x:-x;
}
const LL inf=1e9;
template <class T>
struct segment_tree_min
{
#define chl (k<<1)
#define chr (k<<1|1)
#define mid ((l+r)>>1)
T *t,*tag;
int n;
segment_tree_min(int n) {t=new T[n<<2](); tag=new T[n<<2](); this->n=n;}
void push_up(int k) {t[k]=min(t[chl],t[chr]);}
void push_down(int k,int l,int r)
{
if(!tag[k]) return;
t[chl]+=tag[k]; t[chr]+=tag[k];
tag[chl]+=tag[k]; tag[chr]+=tag[k]; tag[k]=0;
}
void build(int k,int l,int r,T *a)
{
if(l>r) return;
if(l==r) {t[k]=a[l]; return;}
build(chl,l,mid,a); build(chr,mid+1,r,a);
push_up(k);
}
void build(T *a) {build(1,1,n,a);}
void update_add(int k,int l,int r,int ll,int rr,T x)
{
if(l>rr || ll>r) return;
if(l>=ll && r<=rr) {t[k]+=x; tag[k]+=x; return;}
push_down(k,l,r);
update_add(chl,l,mid,ll,rr,x); update_add(chr,mid+1,r,ll,rr,x);
push_up(k);
}
void update_add(int ll,int rr,T x) {update_add(1,1,n,ll,rr,x);}
T query(int k,int l,int r,int ll,int rr)
{
if(l>rr || ll>r) return inf*10000; // attention!
if(l>=ll && r<=rr) return t[k];
push_down(k,l,r);
return min(query(chl,l,mid,ll,rr),query(chr,mid+1,r,ll,rr));
}
T query(int ll,int rr) {return query(1,1,n,ll,rr);}
};
const int maxn=2e5+5;
int H,W,A[maxn],B[maxn];
int main()
{
H=read(),W=read();
REP(i,1,H) A[i]=read(),B[i]=read();
segment_tree_min<LL> t1(W),t2(W);
REP(i,1,W) t2.update_add(i,i,-i);
REP(i,1,H)
{
int r=B[i]+1;
if(r<=W)
{
LL minx=t2.query(1,B[i]);
LL now=t1.query(r,r);
if(now>minx+r)
{
t1.update_add(r,r,minx+r-now);
t2.update_add(r,r,minx-t2.query(r,r));
}
}
t1.update_add(A[i],B[i],inf);
t2.update_add(A[i],B[i],inf);
t1.update_add(1,W,1);
t2.update_add(1,W,1);
LL x=t1.query(1,W);
if(x>=inf) puts("-1");
else printf("%lld\n",x);
}
return 0;
}