zoukankan      html  css  js  c++  java
  • [日常训练]养花(分块+数论)

    Description

    给定一个长度为 \(n\) 的数组 \(a\)

    要求回答 \(m\) 个询问。

    对于每个询问,给出 \(l,r,k\),求 \(max_{i=l}^{r}\left\{ a_i\ \%\ k \right\}\)

    \(1\leq n,a_i,l,r,k \leq 10^5+1\)

    Solution

    分块,块数 \(100\)

    \(f[i][j]\) 表示第 \(i\) 块的数 \(\%j\) 的最大值,考虑怎么求 \(f[i][j]\)

    显然有 \(a_i\%j=a_i-\lfloor\frac{a_i}{j}\rfloor×j\)

    那么枚举 \(k\),在所有满足 \(\lfloor\frac{a_i}{j}\rfloor=k\)\(a_i\) 中取 \(a_i-k×j\) 的最大值。

    这相当于找满足 \(a_i<(k+1)×j\) 的最大的 \(a_i\)

    对于每块,预处理 \(b[x]\) 表示这一块 \(≤ x\) 的数当中的最大值。

    然后枚举 \(j,k\)\(f[i][j]=max(b[(k+1)×j-1]-k×j)\)

    假设 \(n,a_i\) 同阶,那么预处理时间复杂度 \(O(100n\log n)\),常数非常小。

    询问复杂度 \(O(1000m)\)

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    template <class t>
    inline void read(t & res)
    {
    	char ch;
    	while (ch = getchar(), !isdigit(ch));
    	res = ch ^ 48;
    	while (ch = getchar(), isdigit(ch))
    	res = res * 10 + (ch ^ 48);
    }
    
    const int e = 100005, o = 105, m = 100001;
    int f[o][e], n, a[e], bl[e], s, br[e], b[e], bel[e], q;
    
    int main()
    {
    	int i, j, k, now = 0, l, r;
    	read(n); read(q); s = n / 100 + 1;
    	for (i = 1; i <= n; i++) read(a[i]);;
    	for (i = 1; i <= n; i = j + 1)
    	{
    		bl[++now] = i; br[now] = j = min(n, now * s);
    		for (k = i; k <= j; k++) bel[k] = now;
    	}
    	for (i = 1; i <= now; i++)
    	{
    		l = bl[i]; r = br[i];
    		for (j = 1; j <= m; j++) b[j] = 0;
    		for (j = l; j <= r; j++) b[a[j]] = a[j];
    		for (j = 1; j <= m; j++) b[j] = max(b[j], b[j - 1]);
    		for (j = 1; j <= m; j++)
    		for (k = 0; k <= m; k += j)
    		f[i][j] = max(f[i][j], b[min(m, k + j - 1)] - k);
    	} 
    	while (q--)
    	{
    		read(l); read(r); read(k);
    		int pl = bel[l], pr = bel[r], ans = 0;
    		if (pl == pr)
    		{
    			for (i = l; i <= r; i++) ans = max(ans, a[i] % k);
    		}
    		else
    		{
    			for (i = pl + 1; i < pr; i++) ans = max(ans, f[i][k]);
    			for (i = l; i <= br[pl]; i++) ans = max(ans, a[i] % k);
    			for (i = bl[pr]; i <= r; i++) ans = max(ans, a[i] % k);
    		}
    		printf("%d\n", ans);
    	}
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    mybatis05--多条件的查询
    mybatis04--Mapper动态代理实现
    mybatis03--字段名和属性名不一致
    mybatis02--增删改查
    myBatis01
    hibernate12--缓存
    hibernate11--Criteria查询
    hibernate10--命名查询
    hibernate09--连接查询
    (转载)閱讀他人的程式碼(5)找到程式入口,再由上而下抽絲剝繭
  • 原文地址:https://www.cnblogs.com/cyf32768/p/12196042.html
Copyright © 2011-2022 走看看