CSP2020 函式呼叫

2022-07-09 06:39:15 字數 1854 閱讀 3081

1.考慮只有型別1,2的操作的情況:

假設乙個陣列依次執行:a[1]+1, *3, a[1]+2, a[3]+2, *2 

那麼 a[1] = a[1]*3*2 + 1*(3*2) + 2*2 , a[3] = a[3]*3*2 + 2*2 , 陣列其餘元素均乘上3*2=6倍

發現對於乘法操作,在最後給所有陣列元素乘上就好了,

而乙個加法操作帶的係數就等於它後面的所有乘法操作之積

因此可以倒序處理,從後往前記錄已進行的所有乘法操作的積是多少,這樣就能計算出每次加法操作帶的係數是多少

2.考慮型別3的操作:

對於圖上的每個點(代表著一種操作),維護乙個mul,表示執行一次這個操作會給累計的積乘上多少

對於1類操作,它的mul=1;對於2類操作,它的mul就等於它要乘上的值;而對於3類操作,它的mul等於它直接連向的所有點的mul之積

以樣例2為例,點2的mul為2,點3的mul為3,所以點1的mul為6,那麼執行一次操作1就會讓前面執行過的所有的加法操作再乘上6的係數

由題目的條件易得,函式的呼叫關係構成乙個dag

按照拓撲序倒序掃一遍即可處理出mul

對於每種型別1或3的操作,維護乙個k,表示這個操作帶著多少係數

先倒序處理 q 次操作,按照只有型別1,2的方法處理出k,

再把型別3的節點的k下傳到它所包含的的型別1的節點,

即可處理出最終的k

為了確保答案的正確性,必須從後往前倒序處理所有呼叫的函式

#include#include

#include

using

namespace

std;

typedef

long

long

ll;const ll mod=998244353

;const

int n=1000005

;struct

edgeedge[n];

ll a[n];

intn,m,q,f[n],cnt,head[n],d[n],rnd[n],len;

queue

q;struct

funcb[n];

void addedge(int u,int

v)void

tuopu()

}}void

getmul()

}}void

getk()

}}int

main()

else

if(b[i].tp==2

)

else}}

tuopu();

getmul();

scanf("%d

",&q);

for(int i=1;i<=q;i++)

scanf("%d

",&f[i]);

ll now=1

;

for(int i=q;i>=1;i--)

getk();

for(int i=1;i<=n;i++) a[i]=a[i]*now%mod;

for(int i=1;i<=m;i++)

for(int i=1;i<=n;i++)

printf(

"%lld

",a[i]);

return0;

}

CSP2020 函式呼叫

點此看題 從部分分的做法入手,當只有加法操作的時候利用拓撲序下傳標記的方法是明顯的。但是多了乙個乘法,此時不要考慮成 一起乘 這樣攪在一起想是很難受的。其實 a aa 陣列是個空殼子,因為拿到所有2 22操作的乘積是很容易的 直接拓撲 所以我們只用考慮乘法對加法的貢獻。首先我們從大的操作順序上去考慮...

CSP2020 函式呼叫(call)

大概就是對於所有的1 2號操作先不做考慮,先考慮3號 對於所有的3操作將該點與所有的需進行的操作連一條有向邊 然後以操作從後往前拓撲 因為運算元眾多,我們考慮將所有的貢獻統一處理 設乙個mul表示該操作對全域性積的影響 則1號操作的mul為1,2號操作的mul為該點操作的值,而3號操作應該是所有的子...

CSP 2020初賽遊記

第2次參加csp 每天筆試 機試 在家放鬆 寫作業 雞鴨月考 愉快的在別人月考的時候離開雞鴨 坐車,車位置不夠,教練cdc cdccd c向我發出同車邀請,被拒絕 最後做了大巴的司乘專座 快樂 到了紀中門口,還要等cdc cdccd c的小車車到才能下車 明明比三鑫早到結果不能下車,啊這 結果c d...