ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022杭电多校第八场1、7、5

2022-08-15 20:31:22  阅读:115  来源: 互联网

标签:杭电多校 return int 第八 pos -- while 2022 const


1001 Theramore

观察以下两种情况:

以0为例,上图就是说,只要有两个连续的0,我们就可以一直把它们往前移动直到移动到首位。同理只要有两个连续的1我们就可以把它们移动到尾部。

所以可以开一个栈,顺序将字符入栈,一旦遇到连续的0或者1,就把它们删去,在首尾打下标记。

const int N=1e5+5;
int T;
char stk[N],s[N];
int top;

int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%s",s+1);
		int n=strlen(s+1);
		int hh=0,tt=0;
		top=0;
		for(int i=1;i<=n;i++){
			if(!top)stk[++top]=s[i];
			else{
				while(stk[top]==s[i]){
					if(s[i]=='1')tt+=2;
					if(s[i]=='0')hh+=2;
					top--; i++;
				}
				if(i<=n)stk[++top]=s[i];
			}
		}
		
		for(int i=1;i<=hh;i++)printf("%c",'0');
		for(int i=1;i<=top;i++)printf("%c",stk[i]);
		for(int i=1;i<=tt;i++)printf("%c",'1');
		printf("\n");
	}
	return 0;
}

1007 Darnassus

如果把\(|i−j|∗|pi−pj|\)看作边权,题目就是要求最小生成树,但是两两之间建边数量太多了,考虑如何优化这一过程。

可以发现,如果我们选择\((1,2),(2,3),(3,4)....\)这些边,最后边长一定不会超过\(n-1\),所以最小生成树的边长也都不会超过\(n-1\)。因此\(|i−j|∗|pi−pj|\)的其中一部分必然小于等于\(\sqrt{n}\),我们可以枚举这部分边,时间复杂度是\(O(n\sqrt{n})\)。

我们不能对边排序,因为时间复杂度超了,考虑用链表记录每个边权对应的所有边。

(然后加了快读和并查集按秩合并还是超时了qwq我真没办法了)

const int N=5e4+5,M=N*sqrt(N);
typedef long long ll;
int T;
int n,dx;
int p[N],id[N];
int f[N],rk[N];
int top;
int h[N],idx;
int fr[M],e[M],ne[M];

inline int findx(int x){
	if(f[x]!=x)return f[x]=findx(f[x]);
	else return x;
}

inline void merge(int u,int v){
	if(rk[u]<=rk[v])f[u]=v;
	else f[v]=u;
	if(rk[u]==rk[v])rk[v]++;
}

inline void adde(int u,int v,int val){
	fr[idx]=u; e[idx]=v; ne[idx]=h[val]; h[val]=idx++; 
}

inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}

inline void write(ll x)
{
    if(x<0)
        putchar('-'),x=-x;
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
    return;
}

int main(){
	T=read();
	while(T--){
		n=read();
		for(int i=1;i<=n;i++){
			p[i]=read();
			id[p[i]]=i;
			h[i]=-1;
		}
		dx=sqrt(n);
		
		idx=0;
		for(int i=1;i<=n;i++){
			for(int j=i+1;j<=min(n,i+dx);j++){
				int c1=abs(i-j)*abs(p[i]-p[j]);
				int c2=abs(i-j)*abs(id[i]-id[j]);
				if(c1<=n-1)adde(i,j,c1);
				if(c2<=n-1)adde(id[i],id[j],c2);
			}
		}
		
		for(int i=1;i<=n;i++){ f[i]=i; rk[i]=1;}
		
		ll res=0;
		int cnt=0;
		for(int i=1;i<=n-1;i++){
			for(int j=h[i];~j;j=ne[j]){
				int u=fr[j],v=e[j];
				u=findx(u); v=findx(v);
				if(u!=v){
					merge(u,v);
					res+=i;
					cnt++;
					if(cnt>=n-1)break;
				}
			}
			if(cnt>=n-1)break;
		}
		write(res);puts("");
	}
	return 0;
}

1005 Ironforge

std被hack了,听说题目假了。

但是还是有可以学习的地方。关键词:并查集、预处理最小质因子、二分判断一列递增的数中是否存在区间[l,r]中的点。

代码参考:ygg2022 杭电多校(8) 个人题解 更新至7题 - 知乎 (zhihu.com)

const int N=2e5+5;
int T,n,m;
int a[N],b[N];
int l[N],r[N];
int st[N],primes[N],cnt,mp[N];
vector<int>pos[N];

void min_prime(int k){
	for (int i = 2; i <= 200000; i++) {
	    if (mp[i])continue;
	    for (int j = i; j <= 200000; j += i) {
	        if (mp[j] == 0)mp[j] = i;
	    }
	}
}

void Prime_decom(){
	for(int i=1;i<=n;i++){
		int x=a[i];
		while(x>1){
			int p=mp[x];
			while(x%p==0)x/=p;
			pos[p].push_back(i);
		}
	}
}

bool pass(int p,int l,int r){
	if(pos[p].size()==0)return 0;
	else return upper_bound(pos[p].begin(),pos[p].end(),r)-
				lower_bound(pos[p].begin(),pos[p].end(),l);
}

int main(){
	min_prime(N-5);
	scanf("%d",&T);
	while(T--){
		for(int i=1;i<=N-5;i++)pos[i].clear();
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)scanf("%d",&a[i]);
		for(int i=1;i<n;i++)scanf("%d",&b[i]);
		
		Prime_decom();
		
		for(int i=n;i>=1;i--){
			r[i]=i;
			while(r[i]<n && pass(b[r[i]],i,r[i]))r[i]=r[r[i]+1];
		}
		
		for(int i=1;i<=n;i++){
			l[i]=i;
			
			if(i>1 && r[i-1]>=i){
				if(pass(b[i-1],i,r[i])){
					r[i]=r[i-1];
					l[i]=l[i-1];
				}
			}
			else{
				while(1){
					int flag=0;
					while(l[i]>1 && pass(b[l[i]-1],l[i],r[i])){
						l[i]=l[l[i]-1];
                    	flag=1;
					}
					while(r[i]<n && pass(b[r[i]],l[i],r[i])){
						r[i]=r[r[i]+1];
						flag=1;
					}
					if(!flag)break;
				}
			}
		}
		
		int x,y;
		for(int i=1;i<=m;i++){
			scanf("%d%d",&x,&y);
			if(l[x]<=y && r[x]>=y)cout<<"Yes"<<endl;
			else cout<<"No"<<endl;
		}
	}
	return (0-0);
}

标签:杭电多校,return,int,第八,pos,--,while,2022,const
来源: https://www.cnblogs.com/tshaaa/p/16589538.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有