[硫化铂]货币
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=0i−1nxtj,这其实也是对应的所有的颜色在
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)[硫化铂]传染