[2018.10.11 T3] 欠钱

暂无链接

欠钱

题目描述

南极的企鹅王国大学中生活着 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 n5000 m ≤ 10000 m ≤ 10000 m10000
第二种:占 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 nm 大小有一定梯度。
对于所有数据,满足: n ≤ 1 0 5 , m ≤ 1 0 6 , 0 ≤ a , b , c ≤ n n ≤ 10^5, m ≤ 10^6, 0 ≤ a, b, c ≤ n n105m1060a,b,cn 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就能解决所有问题。

LCT.gif

代码
#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();}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值