[2018.10.11 T3] 欠錢
暫無連結
欠錢
題目描述
南極的企鵝王國大學中生活著
只企鵝,作為
世紀的優秀大學生,企鵝們積極響應“大眾創業,萬眾創新”的號召,紛紛創業。但是創業需要資金,企鵝們最近手頭比較緊,只能互相借錢。
企鵝的借錢行為是有規律可循的:每隻企鵝只會借一次錢,並且只會從一隻企鵝那裡借錢。借錢關係中不存在環(即不存在類似“金企鵝欠銀企鵝錢,銀企鵝欠銅企鵝錢,銅企鵝欠金企鵝錢”這種情況)。
企鵝的還錢行為也是有規律可循的:每隻企鵝一旦新獲得了一筆錢,就會立刻用這筆錢儘可能償還自己欠的債務,直到債務償清或用光這筆錢。它只會使用新獲得的這筆錢,至於以前它有沒有錢、有多少錢,與還錢行為無關。
企鵝們經常會做美夢。在一隻企鵝
的夢裡,它夢見自己創業成功,一下子獲得了
元錢,於是(按照上文的還錢規則)它趕快把錢用來還債,接著拿到錢的那隻企鵝也趕快把錢用來還債……如此往復,直到所有獲得錢的企鵝都完成了還債操作。夢醒之後,它開心地把夢的內容告訴了另外一隻企鵝
,企鵝
聽了,也很開心,於是它問道:在你的夢裡,我獲得了多少錢呢? (指
去還債之前手裡的錢,包括後來用於還債的錢和還債後
手裡剩下的錢。 )
夢畢竟是夢,對實際的欠債情況沒有影響。
格式
輸入格式
第一行兩個整數
和
,表示有
只企鵝,
個操作。
接下來
行,有兩種可能的格式:
- :修改操作,企鵝 向企鵝 借了 元錢。
- :查詢操作,詢問假如 有了 元錢,企鵝 會淨收入多少錢。
本題強制線上,也就是說:對於每個操作輸入的變數 (如果沒有 ,那就只有 )都不是實際的 ,想獲得實際的 應當經過以下操作:
a = (a + lastans) % n + 1;
b = (b + lastans) % n + 1;
c = (c + lastans) % n + 1;
其中, 是上一次詢問的答案。如果沒有上一次詢問, 為 。
輸出格式
對每個詢問操作,輸出一行一個數表示答案。
樣例
樣例輸入
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
資料範圍
資料分為以下幾種:
第一種:佔
,
且
;
第二種:佔
,所有借錢事件(
開頭的操作)發生在所有詢問事件(
開頭的操作)之前;
第三種:佔
,對於一隻企鵝
,最多隻有一隻企鵝向
借錢;
第四種:佔
,沒有特殊性質,
大小有一定梯度。
對於所有資料,滿足:
且
。
題解
考場上沒看清題,以為是個 ,於是沒去管,又被 毒瘤,最後沒有時間寫。。。
所以,你特麼為什麼要在 模擬賽 ,放一道 傻逼題呢???
我們只需要一棵維護鏈上最小值的有根 就能解決所有問題。
程式碼
#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();}