[硫化铂]货币

Posted StaroForgin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[硫化铂]货币相关的知识,希望对你有一定的参考价值。

货币

题目描述


题解

首先,如果没有强制在线这个条件的话,应该是相当好做的。
我们可以考虑将整个过程到这来,每次相当于将原来的一个连通块分裂成了两个。
如果我们记录下每个左端点所对应的右端点的话,可以发现,他会对一些区间的右端点进行延伸,相当于给这些区间赋一个最大值改变的标记。
由于我们的右端点是单调不减的,所以我们可以发现,每次我们赋值会使之改变的区间必然是一个连续的区间,我们可以通过线段树上二分找出这个区间,然后在更改就很容易维护我们答案的最大值。
可以发现,当我们合并一个大小为 x x x的集合与一个大小为 y y y的集合时,其在线段树上会影响的区间是 O ( min ⁡ ( x , y ) ) O\\left(\\min(x,y)\\right) O(min(x,y))级别的。
所以我们可以用启发式合并来维护我们的集合,这样的话,我们就可以在 O ( n log ⁡ 2 n ) O\\left(n\\log^2n\\right) O(nlog2n)的时间复杂度内解决这个不强制在线的问题了。

其实强制在线也可以用类似的方法解决。
我们观察到点 i i i的右端点为 max ⁡ j = 0 i − 1 n x t j \\max_j=0^i-1nxt_j maxj=0i1nxtj,这其实也是对应的所有的颜色在 i i i右边的最近点中最远的一个。
我们发现,我们每次启发式合并两个集合,同样也只会影响 O ( min ⁡ ( x , y ) ) O\\left(\\min(x,y)\\right) O(min(x,y))级别的后继。
而正着来的话,我们的右端点是不断变小的,也就是说,当我们更改 x x x时,原来一整个右端点为 n x t x nxt_x nxtx的区间会分裂成多个不超过 n x t x nxt_x nxtx的区间。
事实上,总共会出现的值相同连续区间的个数,是与我们反着来一样的,我们反着来是将多个值不同的区间合并成一个区间,我们正着来则是将一个区间分裂成多个值不同的区间。
由于整个过程中更改区间的总数相同,所以正着来操作次数自然也是 O ( n log ⁡ n ) O\\left(n\\log n\\right) O(nlogn)的,对于每个区间的位置,我们同样可以在线段树上二分求出。

总时间复杂度 O ( n log ⁡ 2 n ) O\\left(n\\log^2n\\right) O(nlog2n)

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define MAXM 200005
#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 int INF=0x3f3f3f3f;
const int mo=998244353;
const int mod=1e5+3;
const int inv2=499122177;
const int jzm=2333;
const int zero=2000;
const int n1=2000;
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 n,q,Typ,fa[MAXN],lastans,cnt[MAXN],siz[MAXN],ans[MAXM],nxt[MAXN],sta[MAXN],stak; 
set<int>s[MAXN],stp;
set<int>::iterator it,jt;
void makeSet(int x)for(int i=1;i<=x;i++)fa[i]=i;
int findSet(int x)return fa[x]==x?x:fa[x]=findSet(fa[x]);
void unionSet(int a,int b)int u=findSet(a),v=findSet(b);if(fa[u]^v)fa[u]=v;
class SegmentTree
	private:
		int maxx[MAXN<<2],mn[MAXN<<2],mx[MAXN<<2],lzy[MAXN<<2];
		void pushup(int rt)
			maxx[rt]=max(maxx[lson],maxx[rson]);
			mn[rt]=min(mn[lson],mn[rson]);
			mx[rt]=max(mx[lson],mx[rson]);
		
		void pushdown(int rt,int l,int r)
			if(lzy[rt])
				int mid=l+r>>1;
				mx[lson]=lzy[rt];lzy[lson]=lzy[rt];
				mx[rson]=lzy[rt];lzy[rson]=lzy[rt];
				mn[lson]=lzy[rt]-mid+1;mn[rson]=lzy[rt]-r+1;
				lzy[rt]=0;
			
		
	public:
		void build(int rt,int l,int r)
			if(l==r)maxx[rt]=mx[rt]=mn[rt]=(l==1)?n:INF;return ; 
			int mid=l+r>>1;build(lson,l,mid);build(rson,mid+1,r);pushup(rt);
		
		void insert(int rt,int l,int r,int ai,int aw)
			if(l>r||l>ai||r<ai)return ;int mid=l+r>>1;
			if(l==r)maxx[rt]=aw;return ;pushdown(rt,l,r);
			if(ai<=mid)insert(lson,l,mid,ai,aw);
			if(ai>mid)insert(rson,mid+1,r,ai,aw);
			pushup(rt);
		
		void modify(int rt,int l,int r,int al,int ar,int aw)
			if(l>r||l>ar||r<al||al>ar)return ;
			if(al<=l&&r<=ar)lzy[rt]=mx[rt]=aw;mn[rt]=aw-r+1;return ;
			int mid=l+r>>1;pushdown(rt,l,r);
			if(al<=mid)modify(lson,l,mid,al,ar,aw);
			if(ar>mid)modify(rson,mid+1,r,al,ar,aw);
			pushup(rt);
		
		int queryPoint(int rt,int l,int r,int al,int ar)
			if(l>r||l>ar||r<al||al>ar)return 0;
			if(al<=l&&r<=ar)return maxx[rt];
			int mid=l+r>>1,res=0;pushdown(rt,l,r);
			if(al<=mid)res=max(queryPoint(lson,l,mid,al,ar),res);
			if(ar>mid)res=max(queryPoint(rson,mid+1,r,al,ar),res);
			return res;
		
		int queryLimit(int rt,int l,int r,int ak)
			if(l==r)return l;if(maxx[rt]<=ak)return r+1;
			int mid=l+r>>1;pushdown(rt,l,r);
			if(maxx[lson]<=ak)return queryLimit(rson,mid+1,r,ak);
			return queryLimit(lson,l,mid,ak);
		
		int ask()return mn[1];
T;
signed main()
	//freopen("currency.in","r",stdin);
	//freopen("currency.out","w",stdout);
	read(n);read(q);read(Typ);makeSet(n);
	for(int i=1;i<=n;i++)s[i].insert(i),siz[i]=1,nxt[i]=INF,stp.insert(i);
	T.build(1,1,n);nxt[0]=n;
	for(int i=1;i<=q;i++)
		int u,v;read(u);read(v);
		u=(u+Typ*lastans-1)%n+1;
		v=(v+Typ*lastans-1)%n+1;
		if(findSet(u)==findSet(v))
			if(!lastans)lastans=n;
			printf("%d\\n",lastans);continue;
		
		u=findSet(u)[硫化铂]传染

[硫化铂]守序划分问题

[硫化铂]密码

[硫化铂]treecnt

[硫化铂]启程的日子

[硫化铂]卿且去