zoukankan      html  css  js  c++  java
  • JZOJ 6847. 【2020.11.03提高组模拟】通往强者之路(找规律+转化题意)

    JZOJ 6847. 【2020.11.03提高组模拟】通往强者之路

    题目大意

    • 初始编号为 i ∈ [ 0 , n ) iin[0,n) i[0,n)的格子上分别有 a i a_i ai砖,每次把第 i i i格的 x x x块砖拿走,放到 [ m a x ( i + 1 , n ) , i + x ] [max(i+1,n),i+x] [max(i+1,n),i+x]上,每格一块,多余的清空,
    • q q q次询问,每次询问操作到格子 q i q_i qi时上面的砖块数量。
    • n , q ≤ 1 0 5 n,qleq 10^5 n,q105 q i ≤ 1 0 18 q_ileq10^{18} qi1018 a i ∈ { n − 1 , n , n + 1 } a_iin{n-1,n,n+1} ai{n1,n,n+1}

    题解

    • 找规律或归纳法证明可以得到每个格子的答案都只有 { n − 1 , n , n + 1 } {n-1,n,n+1} {n1,n,n+1}三种情况,不妨把它们分别看作是 { 0 , 1 , 2 } {0,1,2} {0,1,2}
    • 可以每 n n n个格子分成一段,若前 i − 1 i-1 i1段的答案已经计算出来了,考虑如何计算第 i i i段的答案,
    • f i , j f_{i,j} fi,j表示第 i i i段第 j ( j ∈ [ 0 , n ) ) j(jin[0,n)) j(j[0,n))个格子的答案,若 f i − 1 , j ≥ 1 f_{i-1,j}geq1 fi1,j1,那么 f i , j f_{i,j} fi,j可以加 1 1 1;若 f i − 1 , j − 1 = 2 f_{i-1,j-1}=2 fi1,j1=2,那么 f i , j f_{i,j} fi,j可以加 1 1 1。特别地,若 f i − 2 , n − 1 = 2 f_{i-2,n-1}=2 fi2,n1=2,则 f i , 0 f_{i,0} fi,0可以加 1 1 1
    • 再转化一下,相当于一段格子上叠有若干的砖块,从第 i i i段到第 i + 1 i+1 i+1段的过程相当于把所有第二层的砖块向右推一格,当右边没有砖块时,该砖块就会掉落并不再被推动。特别地,第 i i i段的最后一格砖块向右推直接推到第 i + 2 i+2 i+2段。
    • 那么直接扫一遍求出每个 0 0 0的位置能不能被填上以及什么时候被填上,每个 2 2 2会不会掉落以及什么时候掉落、掉落在哪个位置,最后询问直接 O ( 1 ) O(1) O(1)处理。

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 100010
    #define ll long long
    int p[N], e[N], a[N], q[N];
    int main() {
    	int tn;
    	scanf("%d", &tn);
    	while(tn--) {
    		int n, m, i; ll x;
    		scanf("%d%d", &n, &m);
    		q[0] = 0;
    		for(i = 0; i < n; i++) {
    			scanf("%d", &a[i]), a[i] -= n - 1;
    			e[i] = -1, p[i] = 0;
    		}
    		for(i = 0; i < n; i++) {
    			if(a[i] == 2) q[++q[0]] = i;
    			else if(!a[i] && q[0]) {
    				int t = q[q[0]];
    				e[t] = i, p[i] = i - t + 1;
    				q[0]--; 
    			}
    		}
    		for(i = 0; i < n; i++) {
    			if(!a[i] && !p[i] && q[0]) {
    				int t = q[q[0]];
    				e[t] = i, p[i] = n - t + i + 2;
    				q[0]--;
    			} 
    		}
    		for(i = 1; i <= m; i++) {
    			scanf("%lld", &x);
    			ll t = x / n + 1;
    			if(!a[x % n] && (!p[x % n] || p[x % n] > t)) printf("%d ", n - 1);
    			else {
    				int l = (t - 1) % (n + 1), y = x % n, z;
    				if(y - l == -1) printf("%d ", n);
    				else {
    					if(y - l >= 0) z = y - l; else z = y - l + n + 1;
    					if(a[z] == 2 && (e[z] == -1 || p[e[z]] > t || (p[e[y - l]] == t && e[y - l] > y))) printf("%d ", n + 1);
    					else printf("%d ", n);
    				}
    			} 
    		}
    		printf("
    ");
    	}
    	return 0;
    }
    
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    脏读、不可重复读、幻读
    数据库一致性
    java 不同时间格式转化
    python-walk遍历目录及查找目录小例子
    python_os模块
    python_time模块
    exec和eval内置函数
    python-filter函数
    python-map函数
    python_内置函数
  • 原文地址:https://www.cnblogs.com/LZA119/p/14279515.html
Copyright © 2011-2022 走看看