暂无链接
欠钱
题目描述
南极的企鹅王国大学中生活着
n
n
n只企鹅,作为
21
21
21世纪的优秀大学生,企鹅们积极响应“大众创业,万众创新”的号召,纷纷创业。但是创业需要资金,企鹅们最近手头比较紧,只能互相借钱。
企鹅的借钱行为是有规律可循的:每只企鹅只会借一次钱,并且只会从一只企鹅那里借钱。借钱关系中不存在环(即不存在类似“金企鹅欠银企鹅钱,银企鹅欠铜企鹅钱,铜企鹅欠金企鹅钱”这种情况)。
企鹅的还钱行为也是有规律可循的:每只企鹅一旦新获得了一笔钱,就会立刻用这笔钱尽可能偿还自己欠的债务,直到债务偿清或用光这笔钱。它只会使用新获得的这笔钱,至于以前它有没有钱、有多少钱,与还钱行为无关。
企鹅们经常会做美梦。在一只企鹅
A
A
A的梦里,它梦见自己创业成功,一下子获得了
+
∞
+\infty
+∞元钱,于是(按照上文的还钱规则)它赶快把钱用来还债,接着拿到钱的那只企鹅也赶快把钱用来还债……如此往复,直到所有获得钱的企鹅都完成了还债操作。梦醒之后,它开心地把梦的内容告诉了另外一只企鹅
B
B
B,企鹅
B
B
B听了,也很开心,于是它问道:在你的梦里,我获得了多少钱呢? (指
B
B
B去还债之前手里的钱,包括后来用于还债的钱和还债后
B
B
B手里剩下的钱。 )
梦毕竟是梦,对实际的欠债情况没有影响。
格式
输入格式
第一行两个整数
n
n
n和
m
m
m,表示有
n
n
n只企鹅,
m
m
m个操作。
接下来
m
m
m行,有两种可能的格式:
- 0 a b c 0\ a\ b\ c 0 a b c:修改操作,企鹅 a a a向企鹅 b b b借了 c c c元钱。
- 1 a b 1\ a\ b 1 a b:查询操作,询问假如 a a a有了 + 1 +1 +1元钱,企鹅 b b b会净收入多少钱。
本题强制在线,也就是说:对于每个操作输入的变量 a , b , c a,b,c a,b,c(如果没有 c c c,那就只有 a , b a, b a,b)都不是实际的 a , b , c a, b, c a,b,c,想获得实际的 a , b , c a, b, c a,b,c应当经过以下操作:
a = (a + lastans) % n + 1;
b = (b + lastans) % n + 1;
c = (c + lastans) % n + 1;
其中, l a s t a n s lastans lastans是上一次询问的答案。如果没有上一次询问, l a s t a n s lastans lastans为 0 0 0。
输出格式
对每个询问操作,输出一行一个数表示答案。
样例
样例输入
5 9
0 1 2 1
0 0 1 2
1 0 1
1 2 4
0 2 1 1
1 2 0
0 3 1 0
1 4 2
1 3 4
样例输出
32010
数据范围
数据分为以下几种:
第一种:占
10
%
10\%
10%,
n
≤
5000
n ≤ 5000
n≤5000且
m
≤
10000
m ≤ 10000
m≤10000;
第二种:占
20
%
20\%
20%,所有借钱事件(
0
0
0开头的操作)发生在所有询问事件(
1
1
1开头的操作)之前;
第三种:占
30
%
30\%
30%,对于一只企鹅
A
A
A,最多只有一只企鹅向
A
A
A借钱;
第四种:占
40
%
40\%
40%,没有特殊性质,
n
、
m
n、 m
n、m 大小有一定梯度。
对于所有数据,满足:
n
≤
1
0
5
,
m
≤
1
0
6
,
0
≤
a
,
b
,
c
≤
n
n ≤ 10^5, m ≤ 10^6, 0 ≤ a, b, c ≤ n
n≤105,m≤106,0≤a,b,c≤n 且
a
≠
b
a \neq b
a̸=b。
题解
考场上没看清题,以为是个 D A G \mathcal{DAG} DAG,于是没去管,又被 T 1 \mathcal{T}1 T1毒瘤,最后没有时间写。。。
所以,你特么为什么要在 N O I P \mathcal{NOIP} NOIP模拟赛 T 3 \mathcal{T}3 T3,放一道 L C T \mathcal{LCT} LCT傻逼题呢???
我们只需要一棵维护链上最小值的有根 L C T \mathcal{LCT} LCT就能解决所有问题。
代码
#include<bits/stdc++.h>
#define ls son[v][0]
#define rs son[v][1]
using namespace std;
const int M=2e5+5;
int son[M][2],dad[M],val[M],mn[M],n,m,tot;
bool notroot(int v){return son[dad[v]][0]==v||son[dad[v]][1]==v;}
void up(int v){mn[v]=min(val[v],min(mn[ls],mn[rs]));}
void spin(int v)
{
int f=dad[v],ff=dad[f],k=son[f][1]==v,w=son[v][!k];
if(notroot(f))son[ff][son[ff][1]==f]=v;son[v][!k]=f,son[f][k]=w;
if(w)dad[w]=f;dad[f]=v,dad[v]=ff;
up(f);
}
void splay(int v)
{
for(int f,ff;notroot(v);spin(v))
{
f=dad[v],ff=dad[f];
if(notroot(f))spin((son[f][0]==v)^(son[ff][0]==f)?v:f);
}
up(v);
}
int access(int v){int f=0;for(;v;v=dad[f=v])splay(v),rs=f,up(v);return f;}
void link(int x,int y){splay(x);dad[x]=y;}
void in(){scanf("%d%d",&n,&m);}
void ac()
{
memset(val,127,sizeof(val));
memset(mn,127,sizeof(mn));
tot=n;
for(int i=1,last=0,op,a,b,c;i<=m;++i)
{
scanf("%d%d%d",&op,&a,&b);
a=(a+last)%n+1,b=(b+last)%n+1;
if(op)access(b),(access(a)==b?(splay(b),printf("%d\n",last=min(val[b],mn[son[b][1]]))):(printf("%d\n",last=0)));
else scanf("%d",&c),c=(c+last)%n+1,val[++tot]=c,mn[tot]=c,link(a,tot),link(tot,b);
}
}
int main(){in(),ac();}