首页 > 其他分享 >【题解】[Ynoi2013] 大学

【题解】[Ynoi2013] 大学

时间:2023-03-08 14:13:30浏览次数:42  
标签:ch 题解 Ynoi2013 long 大学 倍数 直接

题目分析:

考虑对于一次修改至少会让 \(x\) 变成 \(\frac{x}{2}\) 所以对于每一个数最多被操作 \(\log{n}\) 次,那么直接暴力操作就好了。
所以其实关键问题是每次怎么找到哪些数是需要被操作的。
看到值域那么小,不难想到可以直接维护 \(f[i]\) 表示 \(i\) 的倍数的数的集合,这样的话直接从这上面找就好了。但是这样还是不行,因为一次操作还是有可能被卡成 \(O(n)\),那么其实就是说我们要做到将已经不是 \(i\) 的倍数的数在访问的时候直接跳过,也就是用类似并查集维护连续段的手段啊。
也就是记 \(p[i][j]\) 表示 \(i\) 的倍数的数里第 \(j\) 个数开始向右第一个仍是 \(i\) 的倍数的数是哪个位置,然后删除就直接并查集的合并就可以了。
对于区间和就直接上树状数组就可以简单维护了。

代码:

因为这个题极致卡常,我没卡过去,所以这个代码过不去的。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e5+5;
int n,a[N];
ll sum[N];
vector<int> f[N],p[N];
inline long long read(){
	long long 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-48;ch=getchar();}
	return x*f;
}
int find(int x,int y){
	if(y == (int)p[x].size())	return y;
	if(p[x][y] == y) return y;
	return p[x][y] = find(x,p[x][y]);	
}
void modify(int x,int y){
	for(int i=x; i<=n; i+=i&(-i))	sum[i] += y;
}
ll query(int x){
	ll ans = 0;
	for(int i=x; i; i-=i&(-i))	ans += sum[i];
	return ans;
}
signed main(){
	int m;n=read();m=read();
	for(int i=1; i<=n; i++){
		a[i]=read();
		for(int j=1; j*j<=a[i]; j++){  //预处理 
			if(a[i] % j == 0){
				f[j].push_back(i);   //f 为具体位置 
				p[j].push_back(p[j].size());   //g 表示这个位置的下一个合法的位置 
				if(j * j != a[i]){
					f[a[i]/j].push_back(i);
					p[a[i]/j].push_back(p[a[i]/j].size());
				}
			}
		}
		modify(i,a[i]);
	} 
	ll lst = 0;
	for(int i=1; i<=m; i++){
		ll opt,l,r,x;opt=read();l=read();r=read();
		l ^= lst;r ^= lst;
		if(opt == 1){
			x=read();
			x ^= lst;
			if(x == 1)	continue;
			int tmp = lower_bound(f[x].begin(),f[x].end(),l) - f[x].begin();
			for(int i=find(x,tmp);i<(int)f[x].size() && f[x][i]<=r;i=find(x,i+1)){   //并查集维护连续段 
				if(a[f[x][i]] % x == 0){
					modify(f[x][i],-a[f[x][i]]);
					modify(f[x][i],a[f[x][i]]/x);
					a[f[x][i]]/=x;
				}
				if(a[f[x][i]] % x != 0)	p[x][i] = i+1;
			}
		}
		else	printf("%lld\n",lst = (query(r) - query(l-1)));
	}
	return 0;
}

标签:ch,题解,Ynoi2013,long,大学,倍数,直接
From: https://www.cnblogs.com/linyihdfj/p/17191801.html

相关文章

  • 大学生如何选择你的第一台服务器?
    如何选择你的第一台服务器?第一步,选择品牌现在主流的云服务器提供商有阿里云、腾讯云、华为云、主推面向企业(百度云、天翼云、金山云)。本人使用过:阿里云、腾讯云、华......
  • QOJ5256 [CERC2022] H. Insertions 题解
    题面题意:给定字符串\(S,T,P\),求将\(T\)插入进\(S\)之后\(P\)最多的出现次数。输出:最多的出现次数;达到这个最多出现次数的插入位置数量;达到这个最多出现次数......
  • 【题解】[Ynoi2010] y-fast trie
    题目分析:显然可以对于所有的\(x\)对\(C\)取模后处理。那么就是两种情况:\(x+y\geC\)\(x+y<C\)对于第一种情况直接找最大的两个数就好了,关键就是第二种情......
  • 杜克大学开源第一个基于边缘计算辅助的V/VI-SLAM地图不确定性量化模型
    以下内容来自小六的机器人SLAM学习圈知识星球每日更新内容点击领取学习资料→机器人SLAM学习资料大礼包论文#AdaptSLAM:Edge-AssistedAdaptiveSLAMwithResource......
  • 春测2023 T2题解
    这是一个从暴力到正解的过程。暴力从\(1\)枚举到\(\sqrtn\),枚举每一个\(x\),进行累乘,顺便用一个map数组判重,时间复杂度\(\mathcal{O}(\sqrtn\logn\logn)\),直接T飞......
  • Ubuntu服务器ssh缓慢问题解决
    Ubuntu服务器ssh缓慢问题解决现象:ssh登陆或su-账号时间较长 排查:1、查看了/var/log/syslog未发现明显报错2、查看/var/log/auth.log发现有pam_systemd:Failedtocreate......
  • AGC060C题解
    Link简要题意:称一个长为\(2^n-1\)的排列\(P\)像堆,如果\(P_i\ltP_{2i}\),且\(P_i\ltP_{2i+1}\)。给定\(a,b\),设\(u=2^a,v=2^{b+1}-1\),在所有像堆的排列中任取......
  • ABC279H 题解
    学考时候推的。场上记错模数,以为是\(998244353\)然后想了半天组合数怎么算)简单题。首先序列问题考虑每个位置的生成函数然后乘起来。位置\(k\)的生成函数显然是\[\s......
  • 字符串的反码【吉林大学考研机试题】
    字符串的反码一个二进制数,将其每一位取反,称之为这个数的反码。下面我们定义一个字符的反码。如果这是一个小写字符,则它和字符a的距离与它的反码和字符z的距离相同;如......
  • 字符串匹配【北京航空航天大学考研机试题】
    字符串匹配给定一个包含n个字符串的字符串数组s1,s2,…,sn和一个短字符串p,找出字符串数组中所有能够和短字符串匹配的字符串。匹配时不区分大小写,短字符串中可能包......