zoukankan      html  css  js  c++  java
  • [做题记录-乱做] [AGC003E] Sequential operations on Sequence

    题意

    一串数,初始为 (1sim n),现在给 (Q) 个操作,每次操作把数组长度变为 (q_i),新增的数为上一个操作后的数组的重复。问 (Q) 次操作后 (1sim n) 每个数出现了多少次。

    [1 leq n leq 10^5 ]

    题解

    为什么题解都说这个很简单啊, 为啥我感觉根本不会啊

    首先可以忽略无效操作让操作序列单增。

    (A_i)表示第(i)次操作以后的数组, 那么(A_i)会是若干倍的(A_{i - 1})加上(A_{i -1})的前面一部分组成。也就是说实际上可以递归地表示(A_i)这个数组。由于最后考虑总答案, 可以倒着做, 设(f_i)表示数组(i)的贡献次数, 倒过来模拟即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    using ll = long long;
    
    #define int long long
    
    int read() {
    	int x = 0, f = 1; char a = getchar();
    	for(; ! isdigit(a); a = getchar()) if(a == '-') f = -1;
    	for(; isdigit(a); a = getchar()) x = x * 10 + a - '0';
    	return x * f;
    }
    
    const int N = 1e5 + 10;
    
    
    
    int n, q, top;
    int stk[N];
    int f[N], g[N];
    
    void calc(int x, int tf) {
    	if(x == 0) return ;
    	int y = upper_bound(stk + 1, stk + 1 + top, x) - stk - 1;
    	if(y == 0) g[1] += tf, g[x + 1] -= tf;
    	else f[y] += x / stk[y] * tf, calc(x % stk[y], tf);
    }
    
    signed main() {
    	n = read(); q = read();
    	stk[++ top] = n;
    	for(int i = 1; i <= q; i ++) {
    		int x = read();
    		while(x <= stk[top]) top --;
    		stk[++ top] = x;		
    	}
    	f[top] = 1;
    	for(int i = top; i >= 2; i --) f[i - 1] += stk[i] / stk[i - 1] * f[i], calc(stk[i] % stk[i - 1], f[i]);
    	g[1] += f[1];
    	g[stk[1] + 1] -= f[1];
    	for(int i = 1; i <= n; i ++) g[i] += g[i - 1];
    	for(int i = 1; i <= n; i ++) printf("%lld%c", g[i], '
    ');
    	return 0;
    }
    
  • 相关阅读:
    循序渐进学习栈和队列
    循序渐进学习数据结构之线性表
    2018 noip 备战日志
    2018 noip 考前临死挣扎
    二维前缀和与差分
    noip模板复习
    宽搜总结
    强联通总结
    二分图再次总结
    NOIP 2016 换教室(期望dp)
  • 原文地址:https://www.cnblogs.com/clover4/p/15360197.html
Copyright © 2011-2022 走看看