欢迎(🍺)back to my blog|

EdGrass

园龄:2年2个月粉丝:10关注:4

Codeforces Round 897 (Div. 2)

A.greengolddog,arrayandpermutation

让大的数减小的数就可以制造更多的不同。

PII a[N];
int ans[N];
void solve(){
    int n=read();
    for(int i=1;i<=n;i++){
        a[i]=make_pair(read(),i);
    }
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++){
        ans[a[i].second]=(n-i+1);
    }
    for(int i=1;i<=n;i++){
        cout<<ans[i]<<" ";
    }
    cout<<'\n';
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

B.XORPalindromes

首先答案显然对称。
找到最小的变化次数然后依次加 2 因为每次可以多变一对,直到加到答案对称的位置。
如果是奇数显然可以多变一个中间的数字,填补变一对的的空缺。

void solve(){
    int n=read();
    string s;
    cin>>s;
    s=' '+s;
    int minn=0;
    for(int i=1;i<=n&&i<=n-i+1;i++){
        if(s[i]!=s[n-i+1])minn++;
    }
    if(n%2==0){
        for(int i=0;i<=n;i++){
            if(minn<=i&&i<=n-minn&&i%2==minn%2){
                cout<<1;
            }else cout<<0;
        }
    }else{
        for(int i=0;i<=n;i++){
            if(minn<=i&&i<=n-minn){
                cout<<1;
            }else cout<<0;
        }
    }
    cout<<'\n';
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

C.Salyg1nandtheMEXGame

每次加入 Mex 即可,感觉很显然啊,这样可以一直逼近 0 ,直到不能再 move
如果想要更大的 Mex 将来不及补缺,不能做到。

int a[N];
void solve(){
    int n=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    int cnt=0,op=a[n]+1;
    for(int i=1;i<=n;i++){
        if(a[i]==cnt)cnt++;
        else {
            op=cnt;
            break;
        }
    }
    while(1){
        cout<<op<<endl;
        int x;
        cin>>x;
        if(x==-1)break;
        op=x;
    }
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

D.CyclicOperations

对位置和点权建边,跑强连通。
如果一个点位于单链上,分析可知一定可以完成赋值的,因为总存在一个点不需要对其他点负责,而且也可以多次对一个点覆盖。
如果一个点位于强连通分量上,显然要大小等于 k ,感觉这个没什么好说的。

int cnt,low[N],num[N],dfn,sccno[N],sta[N],top;
int siz[N];
vector<int>G[N];
void dfs(int u){
    sta[top++]=u;
    low[u]=num[u]=++dfn;
    for(int i=0;i<G[u].size();i++){
        int v=G[u][i];
        if(!num[v]){
            dfs(v);
            low[u]=min(low[v],low[u]);
        }else if(!sccno[v]){
            low[u]=min(low[u],num[v]);
        }
    }
    if(low[u]==num[u]){
        cnt++;
        while(1){
            int v=sta[--top];
            sccno[v]=cnt;
            if(u==v)break;
        }
    }
}
void Tarjan(int n){
    cnt=top=dfn=0;
    for(int i=1;i<=n;i++){
        if(!num[i]){
            dfs(i);
        }
    }
}
void solve(){
    int n=read(),k=read(),ans=1;
    for(int i=0;i<=n+100;i++){
        G[i].clear();
        num[i]=0;
        sccno[i]=0;
        siz[i]=0;
        low[i]=0;
    }
    for(int i=1;i<=n;i++){
        int x=read();
        G[i].push_back(x);
    }
    if(k==1){
        int ok=1;
        for(int i=1;i<=n;i++){
            if(G[i][0]!=i)ok=0;
        }
        puts(ok>0?"YES":"NO");
        return ;
    }
    Tarjan(n);
    for(int i=1;i<=n;i++){
        siz[sccno[i]]++;
    }
    for(int i=1;i<=n;i++){
        if((siz[sccno[i]]==1&&G[i][0]==i)||(siz[sccno[i]]!=1&&siz[sccno[i]]!=k))ans=0;
    }
    puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

E1.Salyg1nandArray(simpleversion)

对于前面的整块显然是直接询问,对于剩下的数字需与最后一个整块合并,每次询问因为会反转,依次问这个区间就可以得到这个区间的异或和。分析我们的询问次数。前半段最多花费 nk 次询问,后半段需要 k 次询问,和不会超过 100 次。

int ask(int x){
    cout<<"? "<<x<<endl;
    return read();
}
void solve(){
    int n=read(),k=read(),ans=0;
    for(int i=1;i+k-1<=n;){
        ans^=ask(i);
        if(i+k*2-1<=n)i+=k;
        else i++;
    }
    cout<<"! "<<ans<<endl;
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

E2.Salyg1nandArray(hardversion)

观察到偶数,说明 (mk)|2 。对于最后的 (n%k)+k 的部分可以通过三次询问得到异或和。假设这段的长度为 m 。那么将其分成长度为 mk2mk22kmmk2 , mk2 五部分。由于询问之后会反转,依次每三段做一次询问,长度都为 k ,且每段最后都被询问奇数次。询问前半段最多花费 nk 次询问,后半段需要 3 次询问,和不会超过 52 次。

int ask(int x){
    cout<<"? "<<x<<endl;
    return read();
}
void solve(){
    int n=read(),k=read(),ans=0;
    for(int i=1;i+k-1<=n;i+=k){
        ans^=ask(i);
    }
    if(n%k){
        ans^=ask(n-k+1-((n%k)>>1));
	    ans^=ask(n-k+1);
    }
    cout<<"! "<<ans<<endl;
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

F.MostDifferentTree

如果我们已经有一颗小子树不与原图 G 中任意一子树相同,那么这个子树向上扩展也不与 G 中任意子树相同。那么这时候我们的目标就变成了找一个最小的未在 G 中出现的树。
用树哈希的方式记录原图的出现的树,然后暴力枚举子树大小,寻找没有出现过的树。
那么进一步研究,可以得出枚举到的可行子树大小必然是一个很小的数字。因为 i 个点构成的不同构二叉树个数是卡特兰数

vector<int>G[N],siz,a,b,c;
vector<vector<int> >nxt;
int num,id[N],n,t,cnt,ans,res;
map<vector<int>,int>mp;
int get(vector<int> &a){
	if(mp.find(a)!=mp.end())    //若存在
        return mp[a];      //返回已有值
	int s=1;   
    for(auto x:a)
        s+=siz[x];  //记录子树大小
	siz.push_back(s);   
    nxt.push_back(a);   //记录后继节点
	int id=mp.size();   //赋值hash
    mp[a]=id;
	return id;
}
void cal(int sur,int lst){
    if(!sur){   //若sur为0
		int k=get(b);   //对空vec取hash
		c.push_back(k); //将hash值记录
		if(k>cnt)ans=res,num=k;	    //如果这个hash值是已记录之外的就是符合要求 记录数据
		return ;
	}
	for(int i=lst;i<a.size();i++){  //递归枚举所有已知子树
		if(siz[a[i]]<=sur){ //如果该子树大小小于目前枚举的值
			b.push_back(a[i]);  //塞入临时vec
			cal(sur-siz[a[i]],i);   //递归
			if(ans)return ; //如果得到合法就return
			b.pop_back();   //删掉刚入队的元素
		}
	}
}
void dfs(int u,int fa){
	vector<int> aa; //新建vec
    aa.clear();
	for(auto v:G[u]){
		if(v==fa)continue;
		dfs(v,u);   //向下递归
		aa.push_back(id[v]);    //将子节点的编号存入vec
	}
	sort(aa.begin(),aa.end());  //对vec排序
	id[u]=get(aa);  //记录hash
    cnt=max(cnt,id[u]); //一共有多少个hash值
	return ;
}
void pr(int x,int y){
    for(auto v:nxt[y]){
        int u=++ans;
        cout<<u<<" "<<x<<"\n";
        pr(u,v);
    }
}
void solve(){
    n=read();
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,0);   //对给定的子树作hash
    for(res=1;res<=n;res++){
        cal(res-1,0);   //暴力处理res个节点的时候 所有可能情况
        if(ans){    //如果可以
            ans=1;
            for(int j=n;j>res;j--,ans++){   //把子树之外的树枝随便构造
                cout<<ans<<" "<<ans+1<<'\n';
            }
            pr(ans,num);    //递归输出子树
            return ;
        }
        a.insert(a.end(),c.begin(),c.end());
        c.clear();
        b.clear(); 
		sort(a.begin(),a.end());
    }
    for(int i=1;i<=n;i++){  //若找不到 输出子树
		for(auto j:G[i]){
			if(i>j)cout<<i<<" "<<j<<"\n";
		}
	}
    //puts(ans>0?"YES":"NO");
    //puts(ans>0?"Yes":"No");
}

本文作者:EdGrass

本文链接:https://www.cnblogs.com/edgrass/p/17694957.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   EdGrass  阅读(173)  评论(0编辑  收藏  举报
   
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 影子 岛屿心情
影子 - 岛屿心情
00:00 / 00:00
An audio error has occurred.

作词 : 张龙/史维旭/刘博宽/格桑咸俊

作曲 : 张龙/史维旭/刘博宽/格桑咸俊

编曲:岛屿心情

总是迷恋水中倒映的自己

总是迷恋水中倒映的自己

总会为你穿上漂亮的外衣

在云端坠落后不堪一击

却仍旧搭起虚幻的云梯

直到没有什么能使你满意

直到没有什么能使你满意

直到那些伤口不再能痊愈

你早已失去了爱的能力

这里的风景还能有什么意义

这是我今生的

这是我今生的

这是我仅剩的

要为你准备多少才将我抛弃

我让你娱乐做你的工具

你可以轻松毁掉一切并嫁祸于我

你可以轻松毁掉一切并嫁祸于我

在这间屋子里我什么都不能说

我爱啊恨啊醉啊

你荡啊荡啊追啊

我是你的影子

我是你的影子

我透过影子追逐你

我透过影子追逐你

我透过影子追逐你

我透过影子追逐你

我透过影子追逐你

我透过影子追逐你

(我早已)

我透过影子追逐你

(看穿了你)

我透过影子追逐你

(我早已)

我透过影子追逐你

(看穿了你)

我透过影子追逐你

(我早已)

我透过影子追逐你

(看穿了你)

我透过影子追逐你

(我不再)

我透过影子追逐你

(不再怕你)

制作人:王大治

制作人:王大治

录音师:杨森 B2

混音师:王大治

录音棚:时音唱片

母带后期:时音唱片