A. AUS
#include <bits/stdc++.h>
using namespace std;
int fa[30];
int get(int x)
{
if(fa[x]==x)
{
return x;
}
return fa[x]=get(fa[x]);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
string s1,s2,s3;
cin>>s1>>s2>>s3;
if(s1.size()!=s2.size())
{
cout<<"NO"<<endl;
continue;
}
if(s1.size()!=s3.size())
{
cout<<"YES"<<endl;
continue;
}
for(int i=0;i<26;i++)
{
fa[i]=i;
}
for(int i=0;i<s1.size();i++)
{
if(s1[i]!=s2[i])
{
fa[get(s1[i]-'a')]=get(s2[i]-'a');
}
}
bool f=false;
for(int i=0;i<s1.size();i++)
{
if(get(s1[i]-'a')!=get(s3[i]-'a'))
{
f=true;
break;
}
}
f==true? cout<<"YES\n":cout<<"NO\n";
}
return 0;
}
K. Kind of Bingo
#include <bits/stdc++.h>
using namespace std;
vector<int>a[100005];
int p[100005],h[100005];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
a[i].clear();
}
for(int i=1;i<=n*m;i++)
{
cin>>p[i];
h[p[i]]=i;
a[p[i]/m+(p[i]%m>0)].push_back(p[i]);
}
if(k>=m)
{
cout<<m<<"\n";
continue;
}
else
{
int ans=n*m;
k=m-k;
for(int i=1;i<=n;i++)
{
ans=min(ans,h[a[i][k-1]]);
}
cout<<max(ans,m)<<"\n";
}
}
return 0;
}
E. Elevator II
#include <bits/stdc++.h>
using namespace std;
struct t1
{
int l,r,id;
}t[100005];
vector<int>ans;
bool cmpl(t1 a,t1 b)
{
return a.l<b.l;
}
bool cmpr(t1 a,t1 b)
{
return a.r<b.r;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
int n,f;
cin>>n>>f;
for(int i=1;i<=n;i++)
{
cin>>t[i].l>>t[i].r;
t[i].id=i;
}
sort(t+1,t+n+1,cmpl);
int p=0,cur=f;
long long sum=0;
ans.clear();
while(p<n)
{
while(p<n&&t[p+1].l<=cur)
{
p++;
sum=sum+t[p].r-t[p].l;
if(t[p].r>cur)
{
ans.push_back(t[p].id);
t[p].id=0;
cur=t[p].r;
}
}
if(p<n)
{
p++;
sum=sum+t[p].r-cur;
cur=t[p].r;
ans.push_back(t[p].id);
t[p].id=0;
}
}
sort(t+1,t+n+1,cmpr);
for(int i=n;i>=1;i--)
{
if(t[i].id)
{
ans.push_back(t[i].id);
}
}
cout<<sum<<"\n";
for(auto x:ans)
{
cout<<x<<" ";
}
cout<<"\n";
}
return 0;
}
M. Make It Divisible
- 一开始觉得程序应该过不去,但还是交了一下,没想到直接过了……本以为是数据弱,后来想了一下好像是自己的时间复杂度算错了,不是\(\sqrt{bi} \cdot n\),是约数个数*n呀!
#include <bits/stdc++.h>
using namespace std;
int b[50005],c[50005],minn,maxn;
long long cnt,sum;
long long n,K;
bool pd()
{
stack<int>s;
for(int i=1;i<=n;i++)
{
while(s.size()&&s.top()>=c[i])
{
if(s.top()%c[i]==0)
{
s.pop();
}
else
{
return false;
}
}
if(s.empty()||c[i]%s.top()==0)
{
s.push(c[i]);
}
else
{
return false;
}
}
return true;
}
void calc(long long k)
{
long long x=(maxn-k*minn)/(k-1);
if(x>=1&&x<=K)
{
for(int i=1;i<=n;i++)
{
c[i]=b[i]+x;
}
if(pd())
{
cnt++;
sum+=x;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
cin>>n>>K;
for(int i=1;i<=n;i++)
{
cin>>b[i];
}
minn=*min_element(b+1,b+n+1);
maxn=*max_element(b+1,b+n+1);
for(int i=1;i<=n;i++)
{
if(b[i]>minn&&b[i]<maxn)
{
maxn=b[i];
}
}
int m=maxn-minn;
if(m==0)
{
cout<<K<<" "<<K*(K+1)/2<<"\n";
continue;
}
cnt=0,sum=0;
for(long long i=1;i*i<=m;i++)
{
if(m%i==0)
{
calc(i+1);
if(i*i!=m)
{
calc(m/i+1);
}
}
}
cout<<cnt<<" "<<sum<<"\n";
}
return 0;
}
H. Heavy-light Decomposition
- 第一遍没构造对也没关系,多做几遍,总会得到正确答案的呀~
- 考虑以最长的一条重链为基础构造,观察到所有长度和它不同的链都可以接在根节点上。如果其他链的长度都比它小,直接这么做就好了;否则,考察是否存在一条长度至少比它短2的链,如果存在,就把它拿出来接在根节点的子节点上,否则无解
#include <bits/stdc++.h>
using namespace std;
struct t1
{
int l,r,len;
}t[100005];
int p[100005];
bool cmp(t1 a,t1 b)
{
return a.len>b.len;
}
int n,k;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
cin>>n>>k;
for(int i=1;i<=k;i++)
{
cin>>t[i].l>>t[i].r;
t[i].len=t[i].r-t[i].l+1;
for(int j=t[i].l;j<t[i].r;j++)
{
p[j+1]=j;
}
}
if(n==1)
{
cout<<"0\n";
continue;
}
sort(t+1,t+k+1,cmp);
p[t[1].l]=0;
if(k==1)
{
for(int i=1;i<n;i++)
{
cout<<p[i]<<" ";
}
cout<<p[n]<<"\n";
continue;
}
if(t[1].len==t[2].len&&t[k].len>=t[1].len-1)
{
cout<<"IMPOSSIBLE"<<"\n";
continue;
}
for(int i=2;i<k;i++)
{
p[t[i].l]=t[1].l;
}
if(t[1].len==t[2].len)
{
p[t[k].l]=t[1].l+1;
}
else
{
p[t[k].l]=t[1].l;
}
for(int i=1;i<n;i++)
{
cout<<p[i]<<" ";
}
cout<<p[n]<<"\n";
}
return 0;
}
F. Fuzzy Ranking
- 眨了一下眼,看见了询问的性质:序列在原图上对应一条链,问题就解决啦!
#include <bits/stdc++.h>
using namespace std;
vector<long long>p[200005],sum[200005];
typedef pair<int,int> pii;
vector<pii>op[200005];
vector<int>a[500005];
int dfn[500005],low[500005],tot,cnt,id[500005];
bool ins[500005];
stack<int>s;
void tarjan(int n1)
{
dfn[n1]=low[n1]=++tot;
s.push(n1);
ins[n1]=true;
for(int i=0;i<a[n1].size();i++)
{
if(!dfn[a[n1][i]])
{
tarjan(a[n1][i]);
low[n1]=min(low[n1],low[a[n1][i]]);
}
else if(ins[a[n1][i]]==true)
{
low[n1]=min(low[n1],dfn[a[n1][i]]);
}
}
if(dfn[n1]==low[n1])
{
cnt++;
while(s.top()!=n1)
{
id[s.top()]=cnt;
ins[s.top()]=false;
s.pop();
}
id[n1]=cnt;
ins[n1]=false;
s.pop();
}
}
long long f(long long x)
{
return x*(x-1)/2;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
int n,k,q;
cin>>n>>k>>q;
for(int i=1;i<=n;i++)
{
a[i].clear();
}
for(int i=1;i<=k;i++)
{
op[i].clear();
sum[i].clear();
p[i].clear();
}
for(int i=1;i<=k;i++)
{
for(int j=1;j<=n;j++)
{
int x;
cin>>x;
if(p[i].size())
{
a[p[i].back()].push_back(x);
}
p[i].push_back(x);
}
}
tot=0;
for(int i=1;i<=n;i++)
{
dfn[i]=0;
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
long long l;
for(int i=1;i<=k;i++)
{
l=0;
for(int j=1;j<n;j++)
{
if(id[p[i][j]]!=id[p[i][j-1]])
{
op[i].push_back(pii(l,j-1));
if(sum[i].size())
{
sum[i].push_back(f(j-l)+sum[i].back());
}
else
{
sum[i].push_back(f(j-l));
}
l=j;
}
}
op[i].push_back(pii(l,n-1));
if(sum[i].size())
{
sum[i].push_back(f(n-l)+sum[i].back());
}
else
{
sum[i].push_back(f(n-l));
}
}
long long ans=0;
for(int i=1;i<=q;i++)
{
int id,l,r;
cin>>id>>l>>r;
id=(id+ans)%k+1;
l=(l+ans)%n;
r=(r+ans)%n;
auto check1=[l](pii x)
{
return x.second<l;
};
auto check2=[r](pii x)
{
return x.first<=r;
};
int p=partition_point(op[id].begin(),op[id].end(),check1)-op[id].begin();
int q=partition_point(op[id].begin(),op[id].end(),check2)-op[id].begin()-1;
if(p==q)
{
ans=f(r-l+1);
}
else
{
ans=sum[id][q-1]-sum[id][p]+f(op[id][p].second-l+1)+f(r-op[id][q].first+1);
}
cout<<ans<<endl;
}
}
return 0;
}
B. Barkley III
- 建立63棵线段树维护1的个数,这种做法显而易见,可是连空间都不够开呀!
- 考虑我们并不关心1的个数,只关心0的个数是否为1,所以我们可以转而维护布尔型变量,可这样时间也不够呀!而且空间还是吃紧
- 等一下,从int到bool,信息量减少了1/32,可是为什么空间只少了1/4?
- 原来,由于内存地址是按字节即 byte 寻址,而非比特 bit,一个 bool 类型的变量,虽然只能表示 0/1, 但是也占了 1 byte 的内存———这正是bitset存在的意义呀!
- 从另一个角度思考,既然每棵线段树之间的操作完全平行,我们完全可以通过状态压缩的方法把它们合并起来呀!
- __builtin_clzll:consecutive、leading、zero
- 用64/32减得位的个数,63/31减得最高位的编号
- 答案错误不要紧,写个朴素程序对拍分分钟的事,错误很快就找出来啦~
- 进入ask函数前也要判断一下这个区间内是否存在答案;这一步看似是log方,其实依然是log,因为只有一个区间会继续递归
- 在ask函数内交叉调用另外的ask函数,看似是2log,其实是log方,因为每次调用都要继续递归下去,所以需要把两个ask函数合并起来,以获得单log的时间复杂度
#include <bits/stdc++.h>
using namespace std;
long long a[1000005];
struct t1
{
int l,r;
long long state,v,bj;
}t[4000005];
void build(int p,int l,int r)
{
t[p].l=l;
t[p].r=r;
t[p].bj=~0ll;
if(l==r)
{
t[p].state=~a[l];
t[p].v=a[l];
return;
}
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].state=(t[p*2].state&t[p*2+1].v)|(t[p*2].v&t[p*2+1].state);
t[p].v=t[p*2].v&t[p*2+1].v;
}
void spread(int p)
{
if(t[p].bj!=(~0ll))
{
t[p*2].bj&=t[p].bj;
t[p*2+1].bj&=t[p].bj;
t[p*2].l==t[p*2].r? t[p*2].state=~(t[p*2].v&t[p].bj):t[p*2].state&=t[p].bj;
t[p*2+1].l==t[p*2+1].r? t[p*2+1].state=~(t[p*2+1].v&t[p].bj):t[p*2+1].state&=t[p].bj;
t[p*2].v&=t[p].bj;
t[p*2+1].v&=t[p].bj;
t[p].bj=~0ll;
}
}
long long ask(int p,int x)
{
if(t[p].l==t[p].r)
{
return t[p].v;
}
spread(p);
if(((t[p*2].v>>x)&1)==0)
{
return ask(p*2,x);
}
else if(((t[p*2+1].v>>x)&1)==0)
{
return ask(p*2+1,x);
}
else
{
return -1;
}
}
long long askop(int p,int l,int r,int x)
{
if(l<=t[p].l&&r>=t[p].r)
{
if(((t[p].v>>x)&1)==0)
{
return ask(p,x);
}
return -1;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
long long val=0;
if(l<=mid)
{
val=askop(p*2,l,r,x);
if(val!=-1)
{
return val;
}
}
if(r>mid)
{
val=askop(p*2+1,l,r,x);
if(val!=-1)
{
return val;
}
}
return -1;
}
typedef pair<long long,long long> pll;
pll Ask(int p,int l,int r)
{
if(l<=t[p].l&&r>=t[p].r)
{
return pll(t[p].v,t[p].state);
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid&&r>mid)
{
auto [lval,lst]=Ask(p*2,l,r);
auto [rval,rst]=Ask(p*2+1,l,r);
return pll(lval&rval,(lst&rval)|(lval&rst));
}
else if(l<=mid)
{
return Ask(p*2,l,r);
}
else
{
return Ask(p*2+1,l,r);
}
}
void change(int p,int l,int r,long long x)
{
if(l<=t[p].l&&r>=t[p].r)
{
t[p].bj&=x;
t[p].l==t[p].r? t[p].state=~(t[p].v&x):t[p].state&=x;
t[p].v&=x;
return;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid)
{
change(p*2,l,r,x);
}
if(r>mid)
{
change(p*2+1,l,r,x);
}
t[p].state=(t[p*2].state&t[p*2+1].v)|(t[p*2].v&t[p*2+1].state);
t[p].v=t[p*2].v&t[p*2+1].v;
}
void change(int p,int l,long long x)
{
if(t[p].l==t[p].r)
{
t[p].state=~x;
t[p].v=x;
return;
}
spread(p);
int mid=(t[p].l+t[p].r)>>1;
if(l<=mid)
{
change(p*2,l,x);
}
else
{
change(p*2+1,l,x);
}
t[p].state=(t[p*2].state&t[p*2+1].v)|(t[p*2].v&t[p*2+1].state);
t[p].v=t[p*2].v&t[p*2+1].v;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
build(1,1,n);
for(int i=1;i<=q;i++)
{
int opt,l,r,s;
long long x;
cin>>opt;
if(opt==1)
{
cin>>l>>r>>x;
change(1,l,r,x);
}
else if(opt==2)
{
cin>>s>>x;
change(1,s,x);
}
else
{
cin>>l>>r;
auto [va,st]=Ask(1,l,r);
cout<<(va|(st&(~askop(1,l,r,63-__builtin_clzll(st)))))<<"\n";
}
}
return 0;
}