The Preliminary Contest for ICPC Asia Xuzhou 2019
Posted codancer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了The Preliminary Contest for ICPC Asia Xuzhou 2019相关的知识,希望对你有一定的参考价值。
B.so easy
并查集,可能会卡掉map,建议使用unordered_map。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
const int mod = 1e9+7;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll llINF = 0x3f3f3f3f3f3f3f3f;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fep(i,a,b) for(int i=(a);i>=(b);i--)
inline bool read(ll &num) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
unordered_map<int,int> par;
int find(int x){
if(par[x]==0){
par[x]=x;
return x;
}
return x==par[x]?x:par[x]=find(par[x]);
}
int main(){
int n,q;
scanf("%d %d",&n,&q);
int op,x;
while(q--){
scanf("%d %d",&op,&x);
if(op==1){
par[find(x)]=x+1;
}else{
if(find(x)>n) puts("-1");
else printf("%d
",find(x));
}
}
return 0;
}
C.Buy Watermelon
签到,大于2的偶数都可以被拆分成两个偶数和。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
const int mod = 1e9+7;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll llINF = 0x3f3f3f3f3f3f3f3f;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fep(i,a,b) for(int i=(a);i>=(b);i--)
inline bool read(ll &num) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
int main(){
// freopen("1.in", "r", stdin);
ll t,n;
read(n);
if(n>2&&(n%2==0)){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
return 0;
}
D. Carneginon
KMP,懒得写了(狗头)。。
E. XKC‘s basketball team
对于每个(i)查找最右的大于等于(a_i+m)的位置。线段树维护区间最大值优先查右子树即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6+100;
const int mod = 1e9+7;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll llINF = 0x3f3f3f3f3f3f3f3f;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fep(i,a,b) for(int i=(a);i>=(b);i--)
inline bool read(ll &num) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
int mxx[N],a[N];
int n,m;
void pushup(int rt){
mxx[rt]=max(mxx[rt<<1],mxx[rt<<1|1]);
}
void buildtree(int rt,int l,int r){
mxx[rt]=0;
if(l==r){
mxx[rt]=a[l];return ;
}
int mid=(l+r)>>1;
buildtree(rt<<1,l,mid);
buildtree(rt<<1|1,mid+1,r);
pushup(rt);
}
int query(int rt,int l,int r,int x){
// cout<<rt<<' '<<l<<' '<<r<<' '<<mxx[rt]<<endl;
if(l==r){
if(mxx[rt]>=x){
return l;
}
else return -1;
}
int mid=(l+r)>>1;
if(mxx[rt<<1|1]>=x){
return query(rt<<1|1,mid+1,r,x);//先查右面
}else{
return query(rt<<1,l,mid,x);
}
}
int main(){
//freopen("1.in", "r", stdin);
scanf("%d %d",&n,&m);
rep(i,1,n) scanf("%d",&a[i]);
buildtree(1,1,n);
vector<int> ans;
rep(i,1,n){
int id=query(1,1,n,a[i]+m);
if(id<=i) ans.push_back(-1);
else{
ans.push_back(id-i-1);
}
}
printf("%d",ans[0]);
rep(i,1,(int)ans.size()-1) printf(" %d",ans[i]);
puts("");
return 0;
}
I. query
对于([1,n]),枚举它们所有的倍数,总对数也就大概只有(O(n cdot log(n))),因此转化为一个正方形,每次查询([l,l])到([r,r])之间点的个数即可。接下来直接离线然后用树状数组维护前缀和即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 2e6+100;
const int mod = 1e9+7;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll llINF = 0x3f3f3f3f3f3f3f3f;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fep(i,a,b) for(int i=(a);i>=(b);i--)
inline bool read(ll &num) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
int n,m;
int c[N];
int lowbit(ll x){
return (x&(-x));
}
void add(ll x,ll v){
for(;x<N;x+=lowbit(x)){
c[x]+=v;
//cout<<x<<' '<<v<<endl;
}
}
ll query(ll x){
ll ans=0;
for(;x;x-=lowbit(x)){
ans+=c[x];
}
return ans;
}
int pos[N],a[N];
int l[N],r[N];
struct point{
int x,y,flag;
}s[N];
bool cmp(point a,point b){
if(a.x==b.x){
if(a.y==b.y){
return a.flag<b.flag;
}
return a.y<b.y;
}
return a.x<b.x;
}
int yy[N],id[N];
map<pair<int,int>,int> mmp;
int main(){
scanf("%d %d",&n,&m);
rep(i,1,n){
scanf("%d",&a[i]);
pos[a[i]]=i;
}
int cnt=0;
rep(i,1,n){
for(int j=2*i;j<=n;j+=i){
s[++cnt]={pos[i],pos[j],0};
}
}
rep(i,1,m){
scanf("%d %d",&l[i],&r[i]);
s[++cnt]={r[i],r[i],1};
s[++cnt]={l[i]-1,r[i],1};
s[++cnt]={r[i],l[i]-1,1};
s[++cnt]={l[i]-1,l[i]-1,1};
}
rep(i,1,cnt) yy[i]=s[i].y;
sort(yy+1,yy+cnt+1);
int siz=unique(yy+1,yy+cnt+1)-yy-1;
sort(s+1,s+cnt+1,cmp);
rep(i,1,cnt){
id[i]=lower_bound(yy+1,yy+siz+1,s[i].y)-yy;
}
rep(i,1,cnt){
if(s[i].flag==0){
add(id[i],1);
}else{
mmp[{s[i].x,s[i].y}]=query(id[i]);
}
}
rep(i,1,m){
printf("%d
",mmp[{r[i],r[i]}]-mmp[{l[i]-1,r[i]}]-mmp[{r[i],l[i]-1}]+mmp[{l[i]-1,l[i]-1}]);
}
return 0;
}
J. Random Access Iterator
首先预处理出每个点所能到达的最大深度和子节点的数量,令(dp[x])表示能到达叶子节点的概率,当从(u)向(v)转移时,只有(v)能到达的的最大深度等于树的深度时才能转移。对于叶子节点:(dp[x]=1),向上转移即可。
[
dp[u]=1-(1- frac{sum{dp[v]}}{|siz[u]|})^{|siz[u]|}
]
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
const int mod = 1e9+7;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll llINF = 0x3f3f3f3f3f3f3f3f;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fep(i,a,b) for(int i=(a);i>=(b);i--)
inline bool read(ll &num) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
ll qpow(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=(ans%mod*a%mod)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans%mod;
}
ll inv(ll a){
return qpow(a,mod-2);
}
vector<int> G[N];
int depth[N],maxxh[N],siz[N];
void dfs(int u,int par){
depth[u]=depth[par]+1;
maxxh[u]=depth[u];
for(int v:G[u]){
if(v==par) continue;
siz[u]++;
dfs(v,u);
maxxh[u]=max(maxxh[u],maxxh[v]);
}
}
ll dp[N];
ll solve(ll u,ll fa){
if(siz[u]==0) return dp[u]=1;
ll ans=0;
for(int v:G[u]){
if(v==fa) continue;
if(maxxh[v]==maxxh[1]){
ans+=solve(v,u);
}
}
ans=ans*inv(siz[u])%mod;
return dp[u]=(1-qpow(1-ans+mod,siz[u])+mod)%mod;
}
int main(){
int n,u,v;
cin>>n;
rep(i,1,n-1){
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,1);
cout<<solve(1,1)<<endl;
return 0;
}
M. Longest subsequence
在(S)中找到最长的子序列使其字典序大于(T),输出长度即可。
假设子序列为(T'),如果(T'>T),则(T')一定存在某个位置(p)使得(T'[1...p-1]=T[1...p]),而(T'[p]>T[p]),枚举(p),利用序列自动机计枚举(T'[p])并快速求的位置,计算答案即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
const int mod = 1e9+7;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll llINF = 0x3f3f3f3f3f3f3f3f;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fep(i,a,b) for(int i=(a);i>=(b);i--)
inline bool read(ll &num) {
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
int nxt[N][27];
void init(char *s){
int l=strlen(s);
for(int i=0;i<26;i++) nxt[l][i]=INF;
for(int i=l-1;i>=0;i--){
for(int j=0;j<26;j++){
nxt[i][j]=nxt[i+1][j];
}
nxt[i][s[i]-'a']=i;
}
}
char s[N],t[N];
int main(){
//freopen("1.in", "r", stdin);
int n,m;
cin>>n>>m;
scanf("%s %s",s,t);
init(s);
int pos=-1;
int ans=0;
int cnt=0;
bool flag=0;
vector<int> id;
for(int i=0;i<n;i++){
for(int j=t[cnt]-'a'+1;j<26;j++){
if(nxt[i][j]!=INF){
flag=1;
ans=max(ans,cnt+n-nxt[i][j]);
}
}
if(s[i]==t[cnt]){
cnt++;
id.push_back(i);
}
if(cnt==m) break;
}
if(!flag){
if(id.size()==m){
if(id[m-1]==n-1)cout<<-1<<endl;
else cout<<m+(n-id[m-1]-1)<<endl;
}
else cout<<-1<<endl;
}
else{
if(id.size()==m&&id[m-1]!=-1){
ans=max(ans,m+(n-id[m-1]-1));
}
cout<<ans<<endl;
}
return 0;
}
以上是关于The Preliminary Contest for ICPC Asia Xuzhou 2019的主要内容,如果未能解决你的问题,请参考以下文章
The Preliminary Contest for ICPC Asia Yinchuan 2019
The Preliminary Contest for ICPC Asia Shenyang 2019
The Preliminary Contest for ICPC Asia Shanghai 2019
The Preliminary Contest for ICPC Asia Shanghai 2019