暂无链接
欠钱
题目描述
南极的企鹅王国大学中生活着nnn只企鹅,作为212121世纪的优秀大学生,企鹅们积极响应“大众创业,万众创新”的号召,纷纷创业。但是创业需要资金,企鹅们最近手头比较紧,只能互相借钱。
企鹅的借钱行为是有规律可循的:每只企鹅只会借一次钱,并且只会从一只企鹅那里借钱。借钱关系中不存在环(即不存在类似“金企鹅欠银企鹅钱,银企鹅欠铜企鹅钱,铜企鹅欠金企鹅钱”这种情况)。
企鹅的还钱行为也是有规律可循的:每只企鹅一旦新获得了一笔钱,就会立刻用这笔钱尽可能偿还自己欠的债务,直到债务偿清或用光这笔钱。它只会使用新获得的这笔钱,至于以前它有没有钱、有多少钱,与还钱行为无关。
企鹅们经常会做美梦。在一只企鹅AAA的梦里,它梦见自己创业成功,一下子获得了+∞+\infty+∞元钱,于是(按照上文的还钱规则)它赶快把钱用来还债,接着拿到钱的那只企鹅也赶快把钱用来还债……如此往复,直到所有获得钱的企鹅都完成了还债操作。梦醒之后,它开心地把梦的内容告诉了另外一只企鹅BBB,企鹅BBB听了,也很开心,于是它问道:在你的梦里,我获得了多少钱呢? (指BBB去还债之前手里的钱,包括后来用于还债的钱和还债后BBB手里剩下的钱。 )
梦毕竟是梦,对实际的欠债情况没有影响。
格式
输入格式
第一行两个整数nnn和mmm,表示有nnn只企鹅,mmm个操作。
接下来mmm行,有两种可能的格式:
- 0 a b c0\ a\ b\ c0 a b c:修改操作,企鹅aaa向企鹅bbb借了ccc元钱。
- 1 a b1\ a\ b1 a b:查询操作,询问假如aaa有了+1+1+1元钱,企鹅bbb会净收入多少钱。
本题强制在线,也就是说:对于每个操作输入的变量a,b,ca,b,ca,b,c(如果没有ccc,那就只有a,ba, ba,b)都不是实际的a,b,ca, b, ca,b,c,想获得实际的a,b,ca, b, ca,b,c应当经过以下操作:
a = (a + lastans) % n + 1;
b = (b + lastans) % n + 1;
c = (c + lastans) % n + 1;
其中,lastanslastanslastans是上一次询问的答案。如果没有上一次询问,lastanslastanslastans为000。
输出格式
对每个询问操作,输出一行一个数表示答案。
样例
样例输入
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≤5000n ≤ 5000n≤5000且m≤10000m ≤ 10000m≤10000;
第二种:占20%20\%20%,所有借钱事件(000开头的操作)发生在所有询问事件(111开头的操作)之前;
第三种:占30%30\%30%,对于一只企鹅AAA,最多只有一只企鹅向AAA借钱;
第四种:占40%40\%40%,没有特殊性质,n、mn、 mn、m 大小有一定梯度。
对于所有数据,满足: n≤105,m≤106,0≤a,b,c≤nn ≤ 10^5, m ≤ 10^6, 0 ≤ a, b, c ≤ nn≤105,m≤106,0≤a,b,c≤n 且 a≠ba \neq ba̸=b。
题解
考场上没看清题,以为是个DAG\mathcal{DAG}DAG,于是没去管,又被T1\mathcal{T}1T1毒瘤,最后没有时间写。。。
所以,你特么为什么要在NOIP\mathcal{NOIP}NOIP模拟赛T3\mathcal{T}3T3,放一道LCT\mathcal{LCT}LCT傻逼题呢???
我们只需要一棵维护链上最小值的有根LCT\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();}