2018年8月7日暑假訓練日記
上午:
HDU 5372 Segment Game(線段樹)
覆蓋區間數=左端點大於L-右端點大於R
由於區間比較大,所以進行離散化處理
然後樹狀陣列維護一下就可以了
The shortest problem(hdu5373+11的倍數)
結論題:能被11整除的數字,奇數和偶數位之和的差可以被11整除。
HDU 5381 The sum of gcd(莫隊+rmq+二分):
由於n比較小先用rmq+二分預處理一下gcd變換的位置
然後莫隊處理區間移動就行了
HDU 5377 Root(擴充套件歐幾里得 + 生成元)
小範圍暴力+大範圍bsgs裸題,因為比較大的質因子只可以有一個
HDU 5386 Cover
逆向思維,在已知結果的前提下看看這個操做是否合法,合法則記錄路徑並更新對應行或者列為任意顏色即可
HDU 5387 Clock
模擬指標的移動就行了,為了防止除不盡,全部擴大120倍在進行處理
下午:
一看1005計算幾何題目有好多人過,找了個假模板搞了兩小時,後來發現就是一個公式,肝到懷疑人生。之後線段樹維護最大值和lazy標記,最後tle,結果賽後改成維護最小值就過了......分析一下應該和資料的隨機性有關係,實際更新次數並不多
上午:
一到比賽就發現線段樹模板沒得用,手敲又種種出錯,所以今天打算看看多校的線段樹題目順便來整理幾套能用的模板,畢竟線段樹是我的專長,老是坑模板有些難受
杭電多校第二場1007 Naive Operations(線段樹七十二變)
之前做的一道線段樹多校題目,維護b[i]-a[i],和最小值,然後如果需要更新暴力更新到單點,同時樹狀陣列維護sum,當時我的思路和題解完全相同,又是沒有模板不敢敲系列
發現越是像線段樹的題目越是沒有什麼膽量寫,這裡維護標記表示該區間的數是否全部修改為斐波那契數,一個數組表示和這個區間最近的斐波那契數,一個維護與這個值最近的斐波那切數,做一般的區間更新和單點更新即可
HDU 5828 多校第八場 1008 Rikka with Sequence(線段樹--資料加強版)
又是一發線段樹優化,區間更新+區間求sqrt+區間查詢
線段樹的時間複雜度真的是個好東西,一開始看的一個題解,分析了半天最後說這個題目我放棄,也是醉了。
細節多點,不過是個線段樹優化的好題,lazy+cover資料優化+輸入掛可過
標程解法用極差,就是區間最大值和區間最小值,若相同,直接開方,若極差為一,也可以特殊處理。不過更新完需要pushdown一次
hdu6070 二分+線段樹 2017多校第四場1004
其實是個0-1的分數規劃,用線段樹維護一下出現的值就可以了,這裡又一次理解了一下0-1規劃
下午:
這裡求gcd和l,r相同的區間的個數
很巧妙的利用了線段樹的性質,找到了每次gcd的下降的位置,記錄達到加速的目的
單點更新,區間查詢(地兵佈陣):
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define maxn 400010
using namespace std;
struct xtree{
long long l,r;
long long sum;
//long long maxx;
//long long minn;
long long mid(){
return (l+r)/2;
}
}tree[maxn];
long long a[maxn];
void pushup(long long id){
tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
//tree[id].maxx=max(tree[id*2].maxx,tree[id*2+1].maxx);
//tree[id].minn=max(tree[id*2].minn,tree[id*2+1].minn);
}
void build(long long id,long long l,long long r){
tree[id].l=l;
tree[id].r=r;
if (l==r){
tree[id].sum=a[l];
//tree[id].maxx=tree[id].minn=a[l];
return ;
}
long long mid=tree[id].mid();
build(id*2,l,mid);
build(id*2+1,mid+1,r);
pushup(id);
}
void update(long long id,long long pos,long long val){
if (tree[id].l==tree[id].r){
tree[id].sum+=val;
//tree[id].maxx=tree[id].minn=tree[id].sum;
return ;
}
long long mid=tree[id].mid();
if (pos<=mid){
update(id*2,pos,val);
}
else {
update(id*2+1,pos,val);
}
pushup(id);
}
long long query(long long id,long long l,long long r){
if (tree[id].l>=l&&tree[id].r<=r){
return tree[id].sum;
}
long long mid=tree[id].mid();
if (r<=mid){
return query(id*2,l,r);
}
else if (l>mid){
return query(id*2+1,l,r);
}
else {
return query(id*2,l,mid)+query(id*2+1,mid+1,r);
}
}
int main(){
long long t;
long long i,j;
long long n,m,x,y,z;
scanf("%lld",&t);
long long cas=0;
while (t--){
scanf("%lld",&n);
for (i=1;i<=n;i++)scanf("%lld",&a[i]);
build(1,1,n);
char fun[11];
printf("Case %lld:\n",++cas);
while (1){
scanf("%s",&fun);
if (fun[0]=='E')break;
else if (fun[0]=='A'){
scanf("%lld%lld",&x,&y);
update(1,x,y);
}
else if (fun[0]=='S'){
scanf("%lld%lld",&x,&y);
update(1,x,-y);
}
else {
scanf("%lld%lld",&x,&y);
long long ans=query(1,x,y);
printf("%lld\n",ans);
}
}
}
}
區間更新,區間查詢(Color the ball):
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
#define maxn 400010
using namespace std;
struct xtree{
long long l,r;
long long lazy;
long long sum;
long long mid(){
return (l+r)/2;
}
}tree[maxn];
long long a[maxn];
void pushup(long long id){
tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;
}
void pushdown(long long id){
if (tree[id].lazy){
tree[id*2].lazy+=tree[id].lazy;
tree[id*2+1].lazy+=tree[id].lazy;
long long mid=tree[id].mid();
tree[id*2].sum+=tree[id].lazy*(mid-tree[id].l+1);
tree[id*2+1].sum+=tree[id].lazy*(tree[id].r-mid);
tree[id].lazy=0;
}
}
void build(long long id,long long l,long long r){
tree[id].l=l;
tree[id].r=r;
tree[id].lazy=0;
if (l==r){
tree[id].sum=0;
//tree[id].sum=a[l];
return ;
}
long long mid=tree[id].mid();
build(id*2,l,mid);
build(id*2+1,mid+1,r);
pushup(id);
}
void update(long long id,long long l,long long r,long long val){
if (tree[id].l>=l&&tree[id].r<=r){
tree[id].lazy+=val;
tree[id].sum+=(tree[id].r-tree[id].l+1)*val;
return ;
}
pushdown(id);
long long mid=tree[id].mid();
if (r<=mid){
update(id*2,l,r,val);
}
else if (l>mid){
update(id*2+1,l,r,val);
}
else {
update(id*2,l,mid,val);
update(id*2+1,mid+1,r,val);
}
pushup(id);
}
long long query(long long id,long long l,long long r){
if (tree[id].l>=l&&tree[id].r<=r){
return tree[id].sum;
}
pushdown(id);
long long mid=tree[id].mid();
if (r<=mid){
return query(id*2,l,r);
}
else if (l>mid){
return query(id*2+1,l,r);
}
else {
return query(id*2,l,r)+query(id*2+1,l,r);
}
}
int main(){
long long n,x,y;
long long i;
while (scanf("%lld",&n)!=EOF&&n){
build(1,1,n);
for (i=1;i<=n;i++){
scanf("%lld%lld",&x,&y);
update(1,x,y,1);
}
for (i=1;i<=n;i++){
printf("%lld%c",query(1,i,i),i==n?'\n':' ');
}
}
}