輸入的第1 行包含兩個數n 和m(m ≤20 000),n 表示初始時數列中數的個數,m表示要進行的運算元目。 第2行包含n個數字,描述初始時的數列。 以下m行,每行一條命令,格式參見問題描述中的**。 任何時刻數列中最多含有500 000個數,數列中任何乙個數字均在[-1 000, 1 000]內。 插入的數字總數不超過4 000 000個,輸入檔案大小不超過20mbytes。
對於輸入資料中的get-sum和max-sum操作,向輸出檔案依次列印結果,每個答案(數字)佔一行。
9 82 -6 3 5 1 -5 -3 6 3
get-sum 5 4
max-sum
insert 8 3 -5 7 2
delete 12 1
make-same 3 3 2
reverse 3 6
get-sum 5 4
max-sum
-110110
題解:
splay,幾乎所有模式都在裡面
注意這個splay維護的是位置
插入:將第pos旋到根,第pos+1(名次樹操作)旋到根的右子樹
這裡的插入用了一種二分的方法,可以保證有序,且可以直接反轉
刪除:將第pos旋到根,第pos+tot+1旋到根的右子樹
如果用了記憶體池還要遞迴**(詳見erase)
反**留下反轉標記,每次直接交換左右節點
修改同上,注意0
求和直接維護
求最大子串行和有點複雜,維護節點最大子串行和,右端最大和,左端最大和,詳見(pushdown)
1 #include2 #include3 #include4 #include5using
namespace
std;
6const
int maxn=500010;7
int tot2,tot1,s[maxn],pre[maxn],ch[maxn][2
],key[maxn],sum[maxn],maxsum[maxn],lx[maxn],rx[maxn],a[maxn];
8int
size[maxn],same[maxn],root,n,m;
9bool
rev[maxn];
10int
gi()
1115
while (ch>='
0'&&ch<='9'
)16
17return s*sign;18}
19void newnode(int &r,int fa,int
k)20
32void pushup(int
x)33
42void update_same(int x,int
c);43
void update_reverse(int
x);44
void pushdown(int
x)45
52if
(rev[x])
5358}59
void build(int &x,int l,int r,int
fa)60
68int getkth(int r,int
k)69
76void rotate(int x,bool
t)77
89void splay(int x,int
goal)
90100
else
101111
else
112116
}117
}118
pushup(x);
119if (goal==0) root=x;
120}
121void insert(int pos,int
tot)
122
127 splay(getkth(root,pos+1),0
);128 splay(getkth(root,pos+2
),root);
129 build(ch[ch[root][1]][0],1,tot,ch[root][1
]);130 pushup(ch[root][1
]);131
pushup(root);
132}
133void erase(int
r)134
140void delete(int pos,int
tot)
141150
void update_same(int x,int
c)151
158void make_same(int pos,int tot,int
c)159
166void update_reverse(int
x)167
173void reverse(int pos,int
tot)
174181
int getsum(int pos,int
tot)
182187
intmax_sum()
188193
intmain()
194
201 lx[root]=rx[root]=maxsum[root]=-2e9;
202 newnode(root,0,-1
);203 newnode(ch[root][1],root,-1
);204 build(ch[ch[root][1]][0],1,n,ch[root][1
]);205 pushup(ch[root][1
]);206
pushup(root);
207for (i=1; i<=m; i++)
208215
else
if (str[0]=='d'
)216
220else
if (str[0]=='
m'&&str[4]=='-'
)221
225else
if (str[0]=='r'
)226
231else
if (str[0]=='g'
)232
237else
if (str[0]=='
m'&&str[3]=='-'
)238
241}
242 }
NOI 2005 維修數列
noi 2005 維修數列 典型的伸展樹模板題 參考 include include include include include using namespace std define key value ch ch root 1 0 const int maxn 500010 const int...
維修數列 NOI2005
好久沒寫題解了 來水一篇題解 請寫乙個程式,要求維護乙個數列,支援以下 6 種操作 輸入的第1行包含兩個數 n 和 m m leq 20 000 n 表示初始時數列中數的個數,m 表示要進行的運算元目。第2行包含 n 個數字,描述初始時的數列。以下 m 行,每行一條命令,格式參見問題描述中的 任何時...
1500 NOI2005 維修數列
題目思路 splay 包括區間插入,區間刪除,記憶體,區間反轉,區間和,區間最大子段,成段更新等操作。include include include include include include include include include include includeusing namesp...