標籤:uid ash images hellip add pid tps 格式 定義
題目描述
有一棵點數為 N 的樹,以點 1 為根,且樹點有邊權。然後有 M 個操作,分為三種:操作 1 :把某個節點 x 的點權增加 a 。操作 2 :把某個節點 x 為根的子樹中所有點的點權都增加 a 。操作 3 :詢問某個節點 x 到根的路徑中所有點的點權和。
輸入輸出格式
輸入格式:
第一行包含兩個整數 N, M 。表示點數和運算元。接下來一行 N 個整數,表示樹中節點的初始權值。接下來 N-1 行每行三個正整數 fr, to , 表示該樹中存在一條邊 (fr, to) 。再接下來 M 行,每行分別表示一次操作。其中第一個數表示該操作的種類( 1-3 ) ,之後接這個操作的參數( x 或者 x a ) 。
輸出格式:
對於每個詢問操作,輸出該詢問的答案。答案之間用換行隔開。
輸入輸出範例輸入範例#1:
5 51 2 3 4 51 21 42 32 53 31 2 13 52 1 23 3
輸出範例#1:
6913
說明
對於 100% 的資料, N,M<=100000 ,且所有輸入資料的絕對值都不
會超過 10^6 。
吐槽
為什麼我這次吐槽要用"標題一"呢?請看這個……從4月1日一直做到6月19日,一道水淋淋的題,給了我血淋淋的教訓——能用函數就盡量用吧,千萬別搞些奇奇怪怪的東西,define定義函數一點都不靠譜啊,大不了用inline,穩得多。之前24分、36分,大片大片地逾時就是因為我用了。
把它換成inline int max()能AC,換成std::max()也能AC。記得樹狀數組裡lowbit函數用define比用inline快一點啊,卡常底層最佳化真是……
解題思路
裸的線段樹,維護最大值即可,lazy都不用(好像也用不成)。聽說也是裸的單調棧來著。
注意事項見上面那個大大的“吐槽”即可
原始碼
#include<stdio.h>#include<string.h>#define lson(x) ((x)<<1)#define rson(x) (((x)<<1)|1)inline int max(int a,int b){ return a>b?a:b;}const int INF = 2000000000;int num=0,tt=0;//樹中元素個數 ,上次查詢結果int m,d;int n;char c;struct seg_tree{ int l,r,max;}t[1000010];//從1起 void maketree(int node,int l,int r){ t[node].l=l; t[node].r=r; t[node].max=-INF; if(l==r) return; int mid=l+r>>1; maketree(lson(node),l,mid); maketree(rson(node),mid+1,r);}int query(int node,int l,int r){ if(l>t[node].r||r<t[node].l) return -INF; if(l<=t[node].l&&r>=t[node].r) return t[node].max; return max(query(lson(node),l,r),query(rson(node),l,r));}void add(int node,int pos,int N){ if(pos<=t[node].r&&pos>=t[node].l) t[node].max=max(t[node].max,N); else return; add(lson(node),pos,N); add(rson(node),pos,N);}int main(){ scanf("%d %d",&m,&d); maketree(1,1,m); for(int i=0;i<m;i++) { scanf("\n%c %d",&c,&n); if(c==‘Q‘) { tt=query(1,num-n+1,num)%d; printf("%d\n",tt); } else { add(1,++num,(n+tt)%d); } } return 0;}
洛穀 P1198 BZOJ 1012 [JSOI2008]最大數