首页 > 其他分享 >[Ynoi2019 模拟赛] Yuno loves sqrt technology I

[Ynoi2019 模拟赛] Yuno loves sqrt technology I

时间:2023-06-19 20:12:02浏览次数:48  
标签:pr Ynoi2019 int sum sqrt st loves NB pl

题目 Link

分块,首先预处理所有整块之间的答案,这部分用类似莫队二离的手法可以改成 \(O(n)\) 次插入和 \(O(n\sqrt{n})\) 查询,然后根号平衡一手做到 \(O(n\sqrt{n})\);空间自然也是能线性的。当然更直白的说法是,直接预处理 \(f(i,j)\) 表示前 \(i\) 块中 \(>j\) 的元素个数。

然后考虑区间 \([l,r]\) 被分成 \(A_1,B,A_2\) 这样的左右散块和整块,那么我们已经处理好了 \(B\to B\),还剩下五块:\(A_1\to A_1/B/A_2,B\to A_2,A_2\to A_2\)。\(A_1\to B,B\to A_2\) 都可以利用 \(f\) 查询出来。

考虑 \(A_1\to A_1\),发现只需要从后往前扫,预处理 \(S_i\) 表示 \(i\) 同块内后面比他小的数的个数,那么只需要查 \(S\) 的区间和。同理 \(A_2\to A_2\) 也可以通过预处理 \(P_i\) 表示同块内前面比他大的数的个数来解决。

最后考虑 \(A_1\to A_2\),考虑提前把每块排序,然后查询的时候尝试归并这两块即可。

还需要考虑同块的情形。考虑差分成 \(P_r\) 减去 \(P_{l-1}\) 再减去 \([L,l-1]\to [l,r]\) 的贡献,其中 \(L\) 是这一块的左端点。那么这个贡献用这一块的排序后的数组也可以轻松算出。

卡到了最优解!

//-DYUNQIAN -std=c++14 -O2 -Wall
#include<bits/stdc++.h>

#define ll long long

using namespace std;

inline ll read(){
	ll x=0;char c=getchar();
	for(;(c<'0'||c>'9');c=getchar());
	for(;(c>='0'&&c<='9');c=getchar())x=x*10+(c&15);
	return x;
}

const int mod=1e9+7;
int ksm(int x,int y,int p=mod){
	int ans=1;
	for(int i=y;i;i>>=1,x=1ll*x*x%p)if(i&1)ans=1ll*ans*x%p;
	return ans%p;
}
int inv(int x,int p=mod){return ksm(x,p-2,p)%p;}
mt19937 rnd(time(0));
int randint(int l,int r){return rnd()%(r-l+1)+l;}

void Assert(bool c,int L=0){if(!c){cout<<"Assertion Failed at "<<L<<endl;exit(0);}}

const int N=1e5+5;
const int B=400;
const int NB=(int)(N/B);

vector<pair<int,int> >ov[NB+5];
#define fi first
#define se second
#define mk make_pair
int n,m,bl[N],st[NB+5],ed[NB+5],f[NB+5][N],pre[N],suf[N],a[N],C,S;
ll ans[NB+5][NB+5],fp[N],fs[N],g[NB+5][N];

struct BIT{
	int c[N];
	int lowbit(int x){return x&(-x);}
	void add(int x,int v){for(int i=x;i<=n;i+=lowbit(i))c[i]+=v;}
	int sum(int x,int res=0){for(int i=x;i;i-=lowbit(i))res+=c[i];return res;}
}T;

ll Q1(int l,int r){
	if(l==st[bl[l]])return fp[r];
	else if(r==ed[bl[r]])return fs[l];
	int p=bl[l],cur=0;ll sum=fp[r]-fp[l-1];
	for(auto t:ov[p]){
		if(t.se<=l-1)cur++;
		else if(t.se>=l&&t.se<=r)sum-=cur;
	}
	return sum;
}
int Q_leq(int l,int r,int v){// st[l] <= j <= ed[r] && a[j] < v
	return f[r][v-1]-f[l-1][v-1];
}
int Q_geq(int l,int r,int v){return ed[r]-st[l]+1-f[r][v-1]+f[l-1][v-1];}
ll query(int l,int r){
	if(bl[l]==bl[r])return Q1(l,r);
	int pl=bl[l],pr=bl[r];
	ll sum=fp[r]+fs[l]+ans[pl+1][pr-1];//A1 -> A1 , A2 -> A2 , B -> B
	
	//A1 -> B & B -> A2 
	sum+=g[pr-1][ed[pl]]-g[pr-1][l-1],sum-=g[pl][ed[pl]]-g[pl][l-1];
	sum-=g[pr-1][r]-g[pr-1][st[pr]-1],sum+=g[pl][r]-g[pl][st[pr]-1];
	sum+=1ll*(ed[pr-1]-st[pl+1]+1)*(r-st[pr]+1);
	
	//A1 -> A2
	int L=ov[pl].size(),p=0,cur=0;
	for(auto t:ov[pr]){
		if(t.se>r)continue;
		while(p<L&&ov[pl][p].fi>t.fi)cur+=(ov[pl][p].se>=l),p++;
		sum+=cur;
	}
	
	return sum;
}

signed main(void){

#ifdef YUNQIAN
	freopen("5046.in","r",stdin);
	freopen("5046.out","w",stdout);
#endif

	n=read(),m=read();S=B;
	for(int i=1;i<=n;i++)a[i]=read();
	
	memset(st,63,sizeof(st));
	for(int i=1;i<=n;i++)bl[i]=(i-1)/S+1,st[bl[i]]=min(st[bl[i]],i),ed[bl[i]]=i;C=bl[n];
	for(int i=1;i<=C;i++){
		for(int j=st[i];j<=ed[i];j++)f[i][a[j]]++;
		for(int j=1;j<=n;j++)f[i][j]+=f[i][j-1];
		for(int j=1;j<=n;j++)f[i][j]+=f[i-1][j];
		
		int now=0;
		for(int j=st[i];j<=ed[i];j++)pre[j]=now-T.sum(a[j]),T.add(a[j],1),now++;
		for(int j=st[i];j<=ed[i];j++)T.add(a[j],-1);now=0;
		for(int j=ed[i];j>=st[i];j--)suf[j]=T.sum(a[j]),T.add(a[j],1);
		for(int j=st[i];j<=ed[i];j++)T.add(a[j],-1);

		for(int j=st[i]+1;j<=ed[i];j++)fp[j]=fp[j-1]+pre[j];
		for(int j=ed[i]-1;j>=st[i];j--)fs[j]=fs[j+1]+suf[j];
		
		for(int j=st[i];j<=ed[i];j++)ov[i].emplace_back(mk(a[j],j));
		sort(ov[i].begin(),ov[i].end());reverse(ov[i].begin(),ov[i].end());
	}
	
	for(int i=1;i<=C;i++){
		int cur=0;
		for(int j=i;j<=C;j++){
			ans[i][j]=ans[i][j-1];
			for(int k=st[j];k<=ed[j];k++)ans[i][j]+=pre[k]+cur-f[j-1][a[k]]+f[i-1][a[k]];
			cur+=ed[j]-st[j]+1;
		}
	}
	
	//g[i][j] = sum{k in [1,j]} f[i][a[k]]
	for(int i=1;i<=C;i++){
		for(int j=1;j<=n;j++)g[i][j]=g[i][j-1]+f[i][a[j]];
	}
	
//	cout<<"prework Time = "<<(clock()-Start)/CLOCKS_PER_SEC<<endl;
	
	ll lans=0;
	for(int i=1;i<=m;i++){
// 		lans=0;
		ll l=read(),r=read();l^=lans,r^=lans;
		cout<<(lans=query(l,r))<<'\n';
	}

	return 0;
}

标签:pr,Ynoi2019,int,sum,sqrt,st,loves,NB,pl
From: https://www.cnblogs.com/YunQianQwQ/p/17492074.html

相关文章

  • Sqrt(x)
    Givenanon-negativeintegerx,returnthesquarerootofxroundeddowntothenearestinteger.Thereturnedintegershouldbenon-negativeaswell.Youmustnotuseanybuilt-inexponentfunctionoroperator.Forexample,donotusepow(x,0.5)inc++o......
  • CF1329E Dreamoon Loves AA 题解
    令\(p_0=0,m\leftarrowm+1,p_{m}=n,a_i=p_i-p_{i-1}\),设在\((p_{i-1},p_i)\)中有\(d_i-1\)个B变成了A,满足\(\sum_{i=1}^m(d_i-1)=k\),让\(k\leftarrowk+m\),这样\(d\)需要满足的限制就变成了\(\sum_{i=1}^md_i=k\)。这也可以看作把\(a_i\)分成\(d_i\)个正整数之......
  • 「解题报告」CF1329E Dreamoon Loves AA
    好题。首先可以把题意转化一下,我们先把每相邻两个A的距离写成一个数组,然后对这个数组进行考虑。那么我们每改一个数,实际上就是将这个数组中的一个数分成两个数,我们要求的就是把这个数组分成\(K=k+m+1\)个数,最小化极差。首先不难得出一点,就是每个数最后肯定是被均分成......
  • CF446C. DZY Loves Fibonacci Numbers
    好牛的题,写一下。题意:维护一个序列\(a\),长度为\(n\),有\(m\)次操作:1lr:对于\(i\in[l,r]\),\(a_i\leftarrowa_i+f_{i-l+1}\)。2lr:求\(\displaystyle\left(\sum_{i=l}^ra_i\right)\bmod(10^9+9)\)。其中\(f_{i}\)表示第\(i\)个斐波那契数(\(f_0=0,f_1=1,f_n=f_......
  • 【CF446C】DZY Loves Fibonacci Numbers(线段树)
    Description给定一个序列,资瓷区间加上一个斐波那契数列,区间求和。Solution有一个性质:fib[a+b]=fib[a−1]×fib[b]+fib[a]×fib[b+1]fib[a+......
  • C#基础 Math Pow Sqrt 幂与平方根
     .NETFramework:4.7.2       IDE:VisualStudioCommunity2019        OS:Windows10x64    typesetting:Markdown codeusingSystem;namespaceConsoleApp{classProgram{staticvoidMain(string[]args){......
  • codeforces#FF DIV2C题DZY Loves Sequences(DP)
    题目地址:http://codeforces.com/contest/447/problem/CC.DZYLovesSequencestimelimitpertestmemorylimitpertestinputoutputa,consistingof nai, ai + 1, .........
  • DZY Loves Colors
    DZYLovesColors题面翻译有一个\(n\)个元素组成的序列,每个元素有两个属性:颜色\(c_i\)和权值\(w_i\)。\(c_i\)初始为\(i\),\(w_i\)初始为\(0\)。\(m\)次操作,操......
  • i < sqrt(n) 和 i*i < n 那一种写法更加高效?
    这两种写法效率依赖处理器、编译器和标准库。一般来说循环内的重复操作的性能差于循环外的单次操作。参考文献Whichismoreefficienttouseinaforloop,i<sqrt(......
  • Codeforces Round #254 (Div. 1) C - DZY Loves Colors 线段树|lazytag维护区间加
    开一个变量维护同一个区间内颜色是否相同,而且显然要用lazytag了递归到颜色相同的区间时就可以直接打标记然后对于标记,维护的就是常规区间加的部分(最开始没写lazy,wa6,没明......