2024.8.20 DS训练
A - Monkey King
可以可并堆,但是我蔡
考虑DSU+启发式合并,发现做完了
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int fa[N];
priority_queue<int> q[N];
int n,m;
int find(int x){
return x==fa[x]?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
fa[x]=y;
while(!q[x].empty()){
q[y].push(q[x].top());
q[x].pop();
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
while(cin>>n){
for(int i=1,in;i<=n;i++){
cin>>in;
fa[i]=i;
while(!q[i].empty()) q[i].pop();
q[i].push(in);
}
cin>>m;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
x=find(x),y=find(y);
if(x==y){
cout<<"-1\n";
continue;
}
if(q[x].size()>q[y].size()) swap(x,y);
int X=q[x].top()/2,Y=q[y].top()/2;
q[x].pop(),q[y].pop();
merge(x,y);
q[y].push(X),q[y].push(Y);
cout<<q[y].top()<<"\n";
}
}
}
B - KUR-Couriers
考虑直接求区间众数
搞了个分块发现没过,原因在于分块空间和时间都很劣,常数大
整个莫队
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5,BL=715;
int n, m;
int a[N];
struct QU {
int l,r,id;
} q[N];
int ans[N];
int len,num,K[N];
int cnt[N];
int L[N],R[N];
bool cmp(QU x,QU y){
return K[x.l]!=K[y.l]?K[x.l]<K[y.l]:x.r<y.r;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++){
cin>>q[i].l>>q[i].r;
q[i].id = i;
}
len=sqrt(n);
num=n/len;
for(int i=1;i<=num;i++){
L[i]=(i-1)*len+1;
R[i]=i*len;
}
if(R[num]!=n){
L[num+1]=R[num]+1;
R[++num]=n;
}
for(int i=1;i<=num;i++) fill(K+L[i],K+R[i]+1,i);
sort(q+1,q+m+1,cmp);
int l=1,r=0,lst=0,mx,fr;
for(int i=1;i<=m;i++){
if(K[q[i].l]!=lst) {
while(r>=l) cnt[a[r--]]--;
mx=0;fr=0;
lst=K[q[i].l];
r=R[lst];
l=r+1;
}
if(K[q[i].l]==K[q[i].r]) {
for(int j=q[i].l;j<=q[i].r;j++)
if(++cnt[a[j]]>mx)
mx=cnt[fr=a[j]];
ans[q[i].id]=mx*2>(q[i].r-q[i].l+1)?fr:0;
for(int j=q[i].l;j<=q[i].r;j++)--cnt[a[j]];
mx=fr=0;
continue;
}
while(r<q[i].r) {
if(++cnt[a[++r]]>mx)
mx=cnt[fr=a[r]];
}
int lol=l,tmp=mx,ffr=fr;
while(lol>q[i].l) {
if(++cnt[a[--lol]]>tmp)
tmp=cnt[ffr=a[lol]];
}
ans[q[i].id]=tmp*2>(q[i].r-q[i].l+1)?ffr:0;
while(lol<l) --cnt[a[lol++]];
}
for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
return 0;
}
C - 不等式组
不妨考虑树状数组,把不等式转化为三类:
恒成立,恒不成立,大于号,小于号
前两种直接记录,后两种上树状数组维护
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5;
int n,C[N],c[N],top,kd[N],k[N],cnt;
char s[20];
bool D[N];
void add(int x,int k,int t[]){
x+=1e6+1;
for(;x<N;x+=x&-x){
t[x]+=k;
}
}
int sum(int x,int t[],int res=0){
x+=1e6+1;
for(;x;x-=x&(-x))
res+=t[x];
return res;
}
int main(){
cin>>n;
int x,y,z;
while(n--){
cin>>s;
if(s[0]=='A'){
cin>>x>>y>>z;
if(!x){
if(y>z){
cnt++;
kd[++top]=3;
}
else kd[++top]=0;
}
if(x>0){
k[++top]=floor((z*1.0-y)/x);
kd[top]=1;
if(k[top]>1e6) kd[top]=0;
else if(k[top]<-1e6){
cnt++;
kd[top]=3;
}
else{
add(k[top],1,C);
}
}
if(x<0){
k[++top]=ceil((z*1.0-y)/x);
kd[top]=2;
if(k[top]<-1e6) kd[top]=0;
else if(k[top]>1e6){
cnt++;
kd[top]=3;
}
else{
add(k[top],1,c);
}
}
}
else if(s[0]=='Q'){
cin>>x;
cout<<sum(x-1,C)+sum(1e6,c)-sum(x,c)+cnt<<"\n";
}
else{
cin>>x;
if(D[x]) continue ;
D[x]=true;
if(kd[x] == 3) cnt--;
if(kd[x] == 1) add(k[x],-1,C);
if(kd[x] == 2) add(k[x],-1,c);
}
}
}
H - Tree Requests
考虑dsu on tree
把询问挂到每个点上
暴力好想,只要出现奇数次的字母数量不超过一即可
套上链分治就做完了的说
#include<bits/stdc++.h>
using namespace std;
#define ei for(int i=hd[x],v;i;i=e[i].nxt)
const int N=1000005;
int n,m;
bool vis[N];
struct edge{
int v,nxt;
}e[N];
int hd[N],cnt;
void add(int u,int v){
e[++cnt]={v,hd[u]},hd[u]=cnt;
e[++cnt]={u,hd[v]},hd[v]=cnt;
}
int sz[N],sum[N],son[N],dep[N],ans[N],tot[N][26];
struct node{
int k,id;
};
vector<node> Q[N];
char s[N];
void dfs(int x,int fa){
sz[x]=1;
dep[x]=dep[fa]+1;
ei{
if((v=e[i].v)==fa) continue;
dfs(v,x);
sz[x]+=sz[v];
if(sz[v]>sz[son[x]]) son[x]=v;
}
}
void calc(int x,int fa,int val){
tot[dep[x]][s[x]-'a']+=val;
ei{
if((v=e[i].v)==fa or vis[v]) continue;
calc(v,x,val);
}
}
bool check(int s[]){
int r=0;
for(int i=0;i<26;++i){
if(s[i]&1) ++r;
if(r>1) return 0;
}
if(r>1) return 0;
return 1;
}
void dfs2(int x,int fa,int keep){
ei{
if((v=e[i].v)==fa or v==son[x]) continue;
dfs2(v,x,0);
}
if(son[x]) dfs2(son[x],x,1),vis[son[x]]=1;
calc(x,fa,1),vis[son[x]]=0;
for(int i=0;i<Q[x].size();++i) ans[Q[x][i].id]=check(tot[Q[x][i].k]);
if(!keep) calc(x,fa,-1);
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=2,u;i<=n;++i){
cin>>u;
add(u,i);
}
cin>>s+1;
dfs(1,0);
for(int i=1,a,b;i<=m;++i){
cin>>a>>b;
Q[a].push_back((node){b,i});
}
dfs2(1,0,0);
for(int i=1;i<=m;++i)
cout<<(ans[i]?"Yes\n":"No\n");
}