231116校内赛

T1 玩具序列

很简单的一道T1但某人的 st 表炸成灰灰了

首先明确我们是需要维护区间最大和最小,那么容易想到的有以下几个:线段树,st 表,单调队列

对于线段树和 st 表而言 \(3e6\) 的数据都有点卡时间

st 表还卡空间,而且预处理慢的离谱,虽然最后卡过去了

如此看来单调队列则是不二之选,我们用双指针挪移了之后便维护一下两个单调队列

在队头出队时记得答案的更改是按队头原序列上的下一个点算而非是新的队头

#include<bits/stdc++.h>
#define N 3000010
using namespace std;
int n,k,mx,mn = 1,a[N],qmx[N],qmn[N],hmx = 1,hmn = 1,tmx,tmn;
signed main(){
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>k>>n;
	for(int i = 1;i<=n;i++)
		cin>>a[i];
	for(int i = 1;i<=n;i++){
		while(hmx<=tmx&&a[qmx[tmx]]<a[i]) tmx--;		
		while(hmn<=tmn&&a[qmn[tmn]]>a[i]) tmn--;
		qmx[++tmx] = i;
		qmn[++tmn] = i;
		while(a[qmx[hmx]]-a[qmn[hmn]]>k){
			if(qmx[hmx]<=qmn[hmn]) mn = qmx[hmx]+1,hmx++;
			else mn = qmn[hmn]+1,hmn++;
		}
		mx = max(mx,i-mn+1);
	}
	cout<<mx;
	return 0;
}

T2 排列

首先我们可以得到 $f(x,y) = f(x/d,y/d) $

所以我们可以只考虑二者互质的情况

还可以发现 \(x+y\) 的值不变,所以只有 \(x+y\)\(2\) 的倍数的情况值才不为 \(0\)

所以只考虑 \(x,y\) 同为奇数的情况

\(x>y\) ,所以 \(f(x,y) = f(2y,x-y)+1\)

可以发现,\(x-y,2y\) 都是偶数

所以同时除二

\(f(x,y) = f(y,\frac {x-y}{2})+1\)

每次除二之后 \(gcd(\frac{x-y}{2},y) = 1\)

所以当 \(x+y\) 为二的整数次幂时 \(\log_2(x+y)\) ,且只有这种情况有值

可以得出 \(f(x,y) = k\) 的个数有大约 \(k2^k\)

\(k\) 不超过 \(\log n\) 所以总数不超过 \(\mathcal O(n\log n)\)

现在我们就可以进一步简化这个问题,把他简化为一个二位偏序问题

#include<bits/stdc++.h>
#define N 3000010
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
struct node{
	int l,r,id;
}q[N];
int n,m,a[N],pos[N],ans[N],t[N];
vector<pii>g[N];
bool cmp(node x,node y){
	return x.l<y.l;
}
void add(int x,int v){
	for(;x<=n;x+=(x&-x))
		t[x]+=v;
}
int query(int x){
	int res = 0;
	for(;x;x-=(x&-x))
		res+=t[x];
	return res;
}
int main(){
	freopen("perm.in","r",stdin);
	freopen("perm.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i = 1;i<=n;i++){
		cin>>a[i];
		pos[a[i]] = i;
	}
	int sum = 4,val = 2;
	while(sum<=2*n){
		for(int i = 1;i*2<sum;i++){
			int x = i,y = sum-i;
			if(y>n) continue;
			if(__gcd(x,y)!=1) continue;
			for(int j = 1;j*y<=n;j++){
				int l = pos[j*x],r = pos[j*y];
				if(l>r) swap(l,r);
				g[l].emplace_back(r,val);
			}
		}
		sum<<=1;
		val++;
	}
	cin>>m;
	for(int i = 1;i<=m;i++){
		cin>>q[i].l>>q[i].r;
		q[i].id = i;
	}
	sort(q+1,q+m+1,cmp);
	int t = n;
	for(int i = m;i>=1;i--){
		while(t>=q[i].l){
			for(pii j: g[t])
				add(j.fi,j.se);
			t--;
		}
		ans[q[i].id] = query(q[i].r);
	}
	for(int i = 1;i<=m;i++)
		cout<<ans[i]<<"\n";
	return 0;
}
posted @ 2023-11-16 19:23  cztq  阅读(3)  评论(0编辑  收藏  举报