zoukankan      html  css  js  c++  java
  • Grakn Forces 题解

    目前进度:A~G

    本来打得还行的一场,D 交了三发罚时,FG 两道蠢题还没做出来……

    最草的是 B 写挂了过了 pretest……看到有人在 hack 还试着锁了一下,然后就 % Alex_Wei 了(

    (讲真感觉 A~E 中也就 B 我比较喜欢吧,比剩下的质量不知道高到哪里去了

    不过掉的不多,海星。


    A

    一位一位填,选任意一个目前不会冲突的数。因为有三个候选,而只有两个邻居,所以一定能有可以选的候选。

    时间复杂度 (O(n))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=100010,mod=998244353;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
    	char ch=getchar();ll x=0,f=0;
    	while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    	return f?-x:x;
    }
    inline int qmo(int x){return x+(x>>31?mod:0);}
    int n,a[3][maxn],ans[maxn];
    void solve(){
    	n=read();
    	FOR(_,0,2) FOR(i,1,n) a[_][i]=read();
    	FOR(i,1,n) ans[i]=0;
    	FOR(i,1,n){
    		int prv=i==1?n:i-1,nxt=i==n?1:i+1;
    		FOR(j,0,2) if(a[j][i]!=ans[prv] && a[j][i]!=ans[nxt]){ans[i]=a[j][i];break;}
    	}
    	FOR(i,1,n) printf("%d ",ans[i]);
    	puts("");
    }
    int main(){
    	int T=read();
    	while(T--) solve();
    }
    

    B

    感觉这难度很不止 B 啊……还出了一堆锅,isaf27 赔钱(

    显然考虑差分。把每个数组都差分。

    第一位无关紧要(可以看成把第一位任意分配,然后把所有数都减去第一个数,显然答案不变)。

    接下来都不考虑第一位。

    现在对每个 (b_i) 序列的限制变成了:非零数的个数不超过 (k-1)

    (a_j=0),显然让每个 (b_{i,j}=0) 最优。

    (a_j e 0),显然让其中一个 (b_{i,j}=a_j),其它都是 (0) 最优。

    那么令 (c)(a_j e 0) 的个数,既然每个序列至多 (k-1) 个,所以至少要 (lceilfrac{c}{k-1} ceil) 个。

    特判 (k=1)

    特判 (c=0),答案不能是 (0)(就是这个把我送走了……)

    时间复杂度 (O(n))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=100010,mod=998244353;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
    	char ch=getchar();ll x=0,f=0;
    	while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    	return f?-x:x;
    }
    inline int qmo(int x){return x+(x>>31?mod:0);}
    int n,k,a[maxn];
    void solve(){
    	n=read();k=read();
    	FOR(i,1,n) a[i]=read();
    	int cnt=0;
    	FOR(i,2,n) if(a[i]!=a[i-1]) cnt++;
    	if(k==1){
    		if(cnt) puts("-1");
    		else puts("1"); 
    	}
    	else printf("%d
    ",max(1,(cnt+k-2)/(k-1)));
    }
    int main(){
    	int T=read();
    	while(T--) solve();
    }
    

    C

    这很应该 swap(B,C) 吧……

    为了方便,加 (0)(l) 两个点。

    (t1_i) 表示第一个人走到第 (i) 个的用时,从上一个点按新速度转移过来即可。

    (t2_i) 类似。

    接下来两人从两边分别走,每次选择最先到达下一个点的人走,直到他们相邻。

    此时再大力上式子。小学课内数学,不再赘述。

    时间复杂度 (O(n))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=100010,mod=998244353;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
    	char ch=getchar();ll x=0,f=0;
    	while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    	return f?-x:x;
    }
    inline int qmo(int x){return x+(x>>31?mod:0);}
    int n,l,a[maxn];
    double t1[maxn],t2[maxn];
    void solve(){
    	n=read();l=read();
    	FOR(i,1,n) a[i]=read();
    	a[n+1]=l; 
    	FOR(i,1,n+1) t1[i]=t1[i-1]+1.0*(a[i]-a[i-1])/i;
    	ROF(i,n,0) t2[i]=t2[i+1]+1.0*(a[i+1]-a[i])/(n-i+1);
    	int l=0,r=n+1;
    	while(l+1<r){
    		if(t1[l+1]<t2[r-1]) l++;
    		else r--;
    	}
    	printf("%.10lf
    ",max(t1[l],t2[r])+1.0*(a[r]-a[l]-fabs(t1[l]-t2[r])*(t1[l]<t2[r]?l+1:n-r+2))/(l+1+n-r+2));
    	FOR(i,1,n) a[i]=t1[i]=t2[i]=0;
    }
    int main(){
    	int T=read();
    	while(T--) solve(); 
    }
    

    D

    设向上 (x) 步,向右 (y) 步(显然操作顺序不影响)。

    枚举 (i,j)。如果第 (i) 个已经不能被第 (j) 个看到,那就大棒子。否则需要满足 (xge c_j-a_i+1)(yge d_j-b_i+1)

    (p_{i,j}=c_j-a_i+1,q_{i,j}=d_j-b_i+1)(只保留一开始能看到的对),把这 (O(nm)) 对排个序(或者开桶也是可以的)。

    枚举 (x),那么会满足 (p_{i,j}le x) 的所有对(所以显然,要么 (x=0),要么 (x) 是某个 (p_{i,j}))。

    对于 (p_{i,j}>x) 的所有对,必须满足 (yge q_{i,j})。因为排过序了形成了个后缀,(y) 就是 (q_{i,j}) 的后缀最大值。

    我比较无脑所以直接排序了,时间复杂度 (O(nmlog nm)),不过好像飞快就不管了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=2020,mod=998244353;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
    	char ch=getchar();ll x=0,f=0;
    	while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    	return f?-x:x;
    }
    inline int qmo(int x){return x+(x>>31?mod:0);}
    int n,m,a[maxn],b[maxn],c[maxn],d[maxn],pl,suf[maxn*maxn],ans=1e9;
    PII p[maxn*maxn];
    int main(){
    	n=read();m=read();
    	FOR(i,1,n) a[i]=read(),b[i]=read();
    	FOR(i,1,m) c[i]=read(),d[i]=read();
    	FOR(i,1,n) FOR(j,1,m){
    		if(c[j]<a[i]) continue;
    		if(d[j]<b[i]) continue; 
    		p[++pl]=MP(c[j]-a[i]+1,d[j]-b[i]+1);
    	}
    	sort(p+1,p+pl+1);
    //	FOR(i,1,pl) printf("(%d,%d)
    ",p[i].first,p[i].second);
    	ROF(i,pl,1) suf[i]=max(suf[i+1],p[i].second);
    	FOR(i,1,pl) if(i==pl || p[i].first!=p[i+1].first) ans=min(ans,p[i].first+suf[i+1]);
    	if(!pl) ans=0;
    	ans=min(ans,p[pl].first);
    	ans=min(ans,suf[1]);
    	printf("%d
    ",ans);
    }
    

    E

    凭啥这个会比 F 过的还少啊 /yiw

    将一个集合内的点连成完全图太烦了,不如每个集合建个虚点,并将所有这里面的数和这个虚点连边。

    实际上就是建出二分图(

    那么原来的一个彩虹环会一一对应现在的简单环。

    要没有环,每个连通块保留最大生成树,把剩下的边删掉即可。

    时间复杂度 (O((n+m+e)log (n+m+e)))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=222222,mod=998244353;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
    	char ch=getchar();ll x=0,f=0;
    	while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    	return f?-x:x;
    }
    inline int qmo(int x){return x+(x>>31?mod:0);}
    struct edge{
    	int u,v,w;
    	bool operator<(const edge &e)const{
    		return w>e.w;
    	}
    }e[maxn];
    int n,m,a[maxn],b[maxn],el,fa[maxn];
    ll ans;
    int getfa(int x){
    	return x==fa[x]?x:fa[x]=getfa(fa[x]);
    }
    int main(){
    	n=read();m=read();
    	FOR(i,1,n) a[i]=read();
    	FOR(i,1,m) b[i]=read();
    	FOR(i,1,n){
    		int l=read();
    		while(l--){
    			int x=read();
    			e[++el]=(edge){i,x+n,a[i]+b[x]};
    			ans+=a[i]+b[x];
    		}
    	}
    	sort(e+1,e+el+1);
    	FOR(i,1,n+m) fa[i]=i;
    	FOR(i,1,el){
    		int u=e[i].u,v=e[i].v,w=e[i].w;
    		u=getfa(u);v=getfa(v);
    		if(u==v) continue;
    		fa[u]=v;
    		ans-=w;
    	}
    	printf("%lld
    ",ans);
    }
    

    F

    推了一整场的假结论,不知道可以把已经搞定的元素变化,白给……

    对于 (n=2^k)(k) 是整数),是可以做到所有数一样的。

    分治,左边和右边一一配对就行了,操作次数 (frac{1}{2}nlog n)。归纳可以证明。

    现在,找到不超过 (n) 的最大的 (2^k),把前 (2^k) 变成一样的,再把后 (2^k) 变成一样的,就行了。

    操作次数 (nlog n)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=555555,mod=998244353;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
    	char ch=getchar();ll x=0,f=0;
    	while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    	return f?-x:x;
    }
    inline int qmo(int x){return x+(x>>31?mod:0);}
    int n,lim=1,ans[maxn][2],al;
    void work(int l,int r){
    	if(l==r) return;
    	int mid=(l+r)>>1;
    	work(l,mid);work(mid+1,r);
    	FOR(i,l,mid) ans[++al][0]=i,ans[al][1]=mid+i-l+1;
    }
    int main(){
    	n=read();
    	while(lim<=n) lim<<=1;
    	lim>>=1;
    	work(1,lim);work(n-lim+1,n);
    	printf("%d
    ",al);
    	FOR(i,1,al) printf("%d %d
    ",ans[i][0],ans[i][1]);
    }
    

    G

    想当年初二的时候,我还能把一个看起来和 kruskal 重构树毫无关系的东西转换成类似 kruskal 重构树的东西……这就是退役的前兆吗 /kk

    看成 (n) 个点的完全图,那么选出来的每个集合所构成的完全图,里面的边权都要小于与相邻点的边权。

    直接 kruskal 重构树。判断每个子树是否能是个完全图,然后直接 DP。

    时间复杂度 (O(n^2))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=1555,mod=998244353;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline ll read(){
    	char ch=getchar();ll x=0,f=0;
    	while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    	return f?-x:x;
    }
    inline int qmo(int x){return x+(x>>31?mod:0);}
    struct edge{
    	int u,v,w;
    	bool operator<(const edge &e)const{
    		return w<e.w;
    	}
    }e[maxn*maxn/2];
    int n,el,cnt,fa[maxn*2],f[maxn*2][maxn],sz[maxn*2],ls[maxn*2],rs[maxn*2],ec[maxn*2];
    int getfa(int x){
    	return x==fa[x]?x:fa[x]=getfa(fa[x]);
    }
    void dfs(int u){
    	if(ls[u] || rs[u]){
    		assert(ls[u] && rs[u]);
    		dfs(ls[u]);dfs(rs[u]);
    		sz[u]+=sz[ls[u]]+sz[rs[u]];
    		FOR(i,1,sz[ls[u]]) FOR(j,1,sz[rs[u]])
    			f[u][i+j]=(f[u][i+j]+1ll*f[ls[u]][i]*f[rs[u]][j])%mod; 
    	}
    	else sz[u]=1;
    	if(ec[u]==sz[u]*(sz[u]-1)/2) f[u][1]=(f[u][1]+1)%mod;
    }
    int main(){
    	cnt=n=read();
    	FOR(i,1,n) FOR(j,1,n){
    		int x=read();
    		if(i<j) e[++el]=(edge){i,j,x};
    	}
    	sort(e+1,e+el+1);
    	FOR(i,1,2*n) fa[i]=i;
    	FOR(i,1,el){
    		int u=e[i].u,v=e[i].v;
    		u=getfa(u);v=getfa(v);
    		if(u==v){ec[u]++;continue;}
    		fa[u]=fa[v]=++cnt;
    		ls[cnt]=u;rs[cnt]=v;
    		ec[cnt]=ec[u]+ec[v]+1;
    	}
    	dfs(cnt);
    	FOR(i,1,n) printf("%d ",f[cnt][i]);
    }
    
  • 相关阅读:
    Pytest 系列(28)- 参数化 parametrize + @allure.title() 动态生成标题
    Pytest 系列(27)- allure 命令行参数
    Pytest 系列(26)- 清空 allure 历史报告记录
    Pytest 系列(25)- 标记用例级别 @allure.
    Pytest 系列(24)- allure 环境准备
    基于Python的三种Bandit算法的实现
    博客迁移
    团体程序设计天梯赛2020游记
    P1825 [USACO11OPEN]Corn Maze S
    # JavaScript中的对象转数组Array.prototype.slice.call()方法详解
  • 原文地址:https://www.cnblogs.com/1000Suns/p/13757363.html
Copyright © 2011-2022 走看看