[AGC003E]Sequential operations on Sequence

2024-03-16 22:32

本文主要是介绍[AGC003E]Sequential operations on Sequence,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Sequential operations on Sequence

题解

其实还是蛮有趣的。

首先,我们发现,我们最后保留下来的,会对我们产生意义的数组操作的长度,一定是递增的。
因为一次减少操作,相当于只给我们保留下来上次操作的一个前缀,相当于上次操作没有增长那么长。
所以我们可以先用一个单调栈维护哪些操作,这样就只剩下增加的操作了。

接下来,我们考虑我们的答案该怎么计算。
显然最开始,我们是一个长度为 q n q_n qn的前缀,出现了一次,由于我们每次是循环式出现,所以我们可以将长度为 q n q_n qn的前缀分解成两部分,一部分是上一个操作的重复出现,一个是一个单独的前缀。
我们发现,对于一个任意长度的前缀,我们都有着类似的分解方式。
譬如一个长度为 y y y的前缀,如果比它小的最长的操作的长度为 x x x,那么我们可以将其分解成 ⌊ y x ⌋ \lfloor\frac{y}{x}\rfloor xy个长度为 x x x的前缀,与 1 1 1个长度为 x % y x\%y x%y的前缀。
我们发现分解成的前缀中, x x x是我们一个操作的长度,我们可以把它当成一个已经出现过的长度,而我们的 x % y x\%y x%y虽然是新出现的,但它显然是小于我们 y y y一半的长度的,所以这样的新增对于一个起点来说,在一条不经过某一个操作长度的路径上,是不会超过 log ⁡ y \log\,y logy次。
我们总共有 m m m个操作长度,也就是说,我们不同长度的数量是不会超过 m log ⁡ n m\log n mlogn,事实上这个上界是极松的,这也就意味着我们可以暴力对每个长度的贡献进行转移。

当一个点转移到小于最短操作长度的位置后,也就意味着它已经贡献到了一个从 1 1 1开始的连续前缀,我们可以先加上一个差分值,最后再后缀和统计答案。
由于我们每次的转移都一定会转移到一个比当前长度小的数,从大到小枚举每个长度进行转移。
枚举的长度虽然是不连续的,但随便找个STL或数据结构就能够很方便的维护了,具体可见代码。

时间复杂度 O ( Q log ⁡ n log ⁡ ( Q log ⁡ n ) ) O\left(Q\log n\log(Q\log n)\right) O(Qlognlog(Qlogn))

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define MAXM 5000005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL; 
typedef long double ld;
typedef pair<int,int> pii;
const double INF=1e9;
const int mo=1e9+7;
const int mod=1e5+3;
const int inv2=5e8+4;
const int jzm=2333;
const int zero=2000;
const int n1=1000;
const int lim=100000;
const int orG=3,ivG=332748118;
const long double Pi=acos(-1.0);
const double eps=1e-12;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
int gcd(int a,int b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1)t=1ll*t*a%p;a=1ll*a*a%p;s>>=1;}return t;}
int Q,stak;LL n,sta[MAXN],ans[MAXN],dp[MAXM];
priority_queue<LL>q;bool vis[MAXM];
struct HashMap{LL val[MAXM];int head[MAXN],tot,nxt[MAXM];int query(LL x){int pos=x%mod,now=head[pos];while(now&&val[now]!=x)now=nxt[now];if(!now)now=++tot,nxt[now]=head[pos],head[pos]=now,val[now]=x;return now;}
}Mp;
signed main(){read(n);read(Q);sta[++stak]=n;for(int i=1;i<=Q;i++){LL x;read(x);while(stak&&x<=sta[stak])stak--;sta[++stak]=x;}int st=Mp.query(sta[stak]),x=stak;dp[st]=1;q.push(sta[stak]);vis[st]=1;while(!q.empty()){LL t=q.top();q.pop();int p=Mp.query(t);if(t<=sta[1]){ans[t]+=dp[p];continue;}while(x&&sta[x]>=t)x--;LL ty=sta[x],tz=t%sta[x];int y=Mp.query(ty);dp[y]+=dp[p]*(t/ty);if(!vis[y])q.push(ty),vis[y]=1;int z=Mp.query(tz);dp[z]+=dp[p];if(!vis[z])q.push(tz),vis[z]=1;}for(int i=sta[1];i>0;i--)ans[i]+=ans[i+1];for(int i=1;i<=n;i++)printf("%lld\n",ans[i]);return 0;
}

谢谢!!!

这篇关于[AGC003E]Sequential operations on Sequence的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/816933

相关文章

浙大数据结构:02-线性结构4 Pop Sequence

这道题我们采用数组来模拟堆栈和队列。 简单说一下大致思路,我们用栈来存1234.....,队列来存输入的一组数据,栈与队列进行匹配,相同就pop 机翻 1、条件准备 stk是栈,que是队列。 tt指向的是栈中下标,front指向队头,rear指向队尾。 初始化栈顶为0,队头为0,队尾为-1 #include<iostream>using namespace std;#defi

【UVA】1626-Brackets sequence(动态规划)

一道算是比较难理解的动规。 状态转移分2个: (用d[i][j]表示在i~j内最少需要添加几个括号,保持平衡) 1.如果s[i]和s[j]是一对括号,那么d[i][j] = d[i + 1][j - 1] 2.否则的话 d[i][j] = min(d[i][k],[k + 1][j]); 边界是d[i + 1][i] = 0; d[i][i] = 1; 13993644 162

【UVA】10534 - Wavio Sequence(LIS最长上升子序列)

这题一看10000的数据量就知道必须用nlog(n)的时间复杂度。 所以特意去看了最长上升子序列的nlog(n)的算法。 如果有2个位置,该位置上的元素为A[i]和A[j],并且他们满足以下条件: 1.dp[i] = dp[j]    (dp[x]代表以x结尾的最长上升子序列长度) 2.A[i] < A[j] 3.i < j 那么毫无疑问,选择dp[i] 一定优于选择dp[j] 那么

2015年多校联合训练第一场OO’s Sequence(hdu5288)

题意:给定一个长度为n的序列,规定f(l,r)是对于l,r范围内的某个数字a[i],都不能找到一个对应的j使得a[i]%a[j]=0,那么l,r内有多少个i,f(l,r)就是几。问所有f(l,r)的总和是多少。 公式中给出的区间,也就是所有存在的区间。 思路:直接枚举每一个数字,对于这个数字,如果这个数字是合法的i,那么向左能扩展的最大长度是多少,向右能扩展的最大长度是多少,那么i为合法的情况

NYOJ 763 Vawio Sequence

OJ题目 : 戳这里~ 描述 Vawio Sequence is very funny,it is a sequence of integers. It has some interesting properties. ·   Vawio is of odd length i.e. L = 2*n + 1. ·  The first (n+1) integers of  Vawio s

python中使用FormatDataLibsvm转为txt文件后报错illegal multibyte sequence

‘gbk’ codec can’t decode byte 0xff in position 0: illegal multibyte sequence 这个报错是因为编码不对,正确的编码是ANSI编码,txt文件打开后另存为可以看到当前的文本文档编码 但是excel不能直接保存ANSI编码的txt文件 所以不能直接保存为ANSI编码 有两种解决办法 1.新建一个txt文件(新建的txt文件

[LeetCode] 128. Longest Consecutive Sequence

题:https://leetcode.com/problems/longest-consecutive-sequence/description/ 题目 Given an unsorted array of integers, find the length of the longest consecutive elements sequence. Your algorithm should

UVa 11992 Fast Matrix Operations 线段树

UVa 11992 Fast Matrix Operations 题目大意:有一个r行c列的全0矩阵,支持三种操作: 1 x1 y1 x2 y2 v 子矩阵(x1,y1,x2,y2)的所有元素增加v(v > 0)。 2 x1 y1 x2 y2 v 子矩阵(x1,y1,x2,y2)的所有元素设为v(v > 0)。 3 x1 y1 x2 y2    查询子矩阵(x1,y1,x2,y2

【ZOJ】3889 Making Sequence【构造】

传送门:【ZOJ】3889 Making Sequence 根据题意构造即可。ZOJ月赛我们抢的第二个FBwww my  code: my~~code: #include <bits/stdc++.h>using namespace std ;typedef unsigned long long ULL ;const int MAXN = 205 ;ULL n , a , b , s ,

CodeForces 487C Prefix Product Sequence

题意: 构造一个1~n的排列  使得n个前缀积%n是一个0~n-1的排列 思路: 首先确定n一定放最后  要不然会有%n会有多个0  这时n-1位置的前缀积为(n-1)! 接着讨论n  n为合数时只有n=4有解  因为如果n为合数一定可以拆成p*q的形式  明显pq|(n-1)! 然后构造ai=(i+1)*inv[i]  因为(i+1)*inv[i] == (j+1)*inv[j]时一