E. Two Small Strings
题意
给你
n
n
n个
a
、
b
、
c
a、b、c
a、b、c,组成一个字符串
并且给定两个长度为2的字符串,使得你得到的串没有这个子串。
题解
构造一组 a b c abc abc的全排列,重复 n n n次,每种字符串最多 6 6 6个子串,一旦出现相同的,就可以交换位置,如果还会出现相同的可以继续交换位置,因为只有两个这样做是绰绰有余的,不会出现交换两次之后会出现之前的子串的。
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e6+50;
int main(){
int n;
string s,t;
cin>>n>>s>>t;
string abc="abc";
vector<string>res;
do{
string cur;
FOR(i,1,n)cur+=abc;
res.push_back(cur);
res.push_back(string(n,abc[0])+string(n,abc[1])+string(n,abc[2]));
}while(next_permutation(abc.begin(),abc.end()));
for(auto str:res){
if(str.find(s)==string::npos&&str.find(t)==string::npos){
cout<<"YES"<<endl<<str<<endl;
return 0;
}
}
cout<<"NO"<<endl;
return 0;
}
F. Unstable String Sort
题意
给你两个序列,构造一个字符串。
使得
a
[
p
i
]
<
=
a
[
p
i
+
1
]
a[p_i]<=a[p_{i+1}]
a[pi]<=a[pi+1]
题解
核心在于不同的部分,如果这两部分的值不相同的话,一定不满足条件,所以容易证明,对于一段区间内两个数组的数构成的集合相同的话,就是全部相同的。
按照这样构造即可,集合相同可以用
s
e
t
set
set处理,每次加入之前判断有没有,有的话选择删,如果set大小为
0
0
0说明形成了这样的集合。
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
string str;
set<int>st;
int A[maxn],B[maxn];
int main(){
str="";
int n,k;
cin>>n>>k;
FOR(i,1,n)scanf("%d",&A[i]);
FOR(i,1,n)scanf("%d",&B[i]);
int pos=-1,cnt=0;
for(int i=1;i<=n;i++){
if(st.find(A[i])!=st.end())st.erase(A[i]);
else st.insert(A[i]);
if(st.find(B[i])!=st.end())st.erase(B[i]);
else st.insert(B[i]);
cnt++;
if(st.empty()){
if(pos+1<26){
FOR(j,1,cnt)str+=char('a'+pos+1);
pos++;
}
else FOR(j,1,cnt)str+='z';
cnt=0;
}
}
string ans=str;
if(pos+1>=k){
cout<<"YES"<<endl;
for(int i=1;i<=n;i++){
ans[A[i]-1]=str[i-1];
}
cout<<ans<<endl;
}
else puts("NO");
}
G. Path Queries
题意
求树上点对,满足点对之间的所有边的最大边小于等于
k
k
k
处理多个询问
题解
可以离线做,按边权把所有边加进去,对于已经形成连通块的部分,显然任意取两个点都可以。
然后就结束了
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
struct node{
int from,to,dist;
friend bool operator < (node a,node b){
return a.dist<b.dist;
}
}A[maxn];
struct query{
int x,id;
friend bool operator < (query a,query b){
return a.x<b.x;
}
}Q[maxn];
ll ans[maxn];
int f[maxn],sz[maxn];
int find(int x){return f[x]==x?x:(f[x]=find(f[x]));}
int main(){
int n,m;
cin>>n>>m;
FOR(i,1,n-1){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
A[i]=node{u,v,w};
}
FOR(i,1,n)f[i]=i,sz[i]=1;
sort(A+1,A+n);
int pos=0;ll now=0;
FOR(i,1,m)scanf("%d",&Q[i].x),Q[i].id=i;
sort(Q+1,Q+1+m);
FOR(i,1,m){
while(pos<n-1&&A[pos+1].dist<=Q[i].x){
pos++;
int u=find(A[pos].from),v=find(A[pos].to);
now-=1ll*sz[u]*(sz[u]-1)/2+1ll*sz[v]*(sz[v]-1)/2;
sz[u]+=sz[v];
f[v]=u;
now+=1ll*sz[u]*(sz[u]-1)/2;
}
ans[Q[i].id]=now;
}
FOR(i,1,m)printf("%lld ",ans[i]);
}