題目鏈結
求三元組的嚴格上公升子串行
先考慮暴力\(dp\)一下
for(int i = 1;i <= n;++i)
for(int j = 1;j < i;++j)
if(x[i] > x[j] && y[i] > y[j] && z[i] > z[j])
f[i] = max(f[i],f[j] + 1)
考慮用\(cdq\)分治優化這個\(dp\)。
大體思路是,先按照第一維排序,保證第一維是嚴格上公升的。然後\(cdq\)一下第二維。樹狀陣列維護第三維(需要先離散化)。這裡用到的是樹狀陣列維護字首最大值。
有兩個\(bug\)調了很久。
直接套用了三維偏序的板子。其實這個題在\(cdq\)的時候是不能像這樣的
void cdq(int l,int r)
因為在\(cdq\)右邊之前,必須保證右邊已經從左邊獲取過答案了。這就是求\(lis\)與求三維偏序不同的地方。
正確操作應該是
void cdq(int l,int r)
其實這個\(bug\)挺\(low\)的,感覺自己智障了2333
因為題目中說必須是嚴格遞增的。所以\(mid\)的位置就不能直接取中間了。
需要找到乙個\(x[mid]\)與\(x[mid + 1]\)不同的位置。
/*
* @author: wxyww
* @date: 2019-02-15 10:45:05
* @last modified time: 2019-02-16 15:29:12
*/#include#include#include#include#include#include#include#include#includeusing namespace std;
typedef long long ll;
const int n = 300000 + 10;
mapma;
ll read()
while(c>='0'&&c<='9')
return x*f;
}int ls[n],tree[n];
struct node a[n];
ll a,p,n;
int js;
void clear(int pos)
}void update(int pos,int x)
}int query(int pos)
return ret;
}node tmp[n];
bool cmp(node x,node y)
bool cmy(node x,node y)
void cdq(int l,int r)
else a[r].ans = max(a[r].ans,query(a[r].x[3] - 1) + 1),++r;
}while(r <= r) a[r].ans = max(a[r].ans,query(a[r].x[3] - 1) + 1),++r;
for(int i = l;i <= l;++i) clear(a[i].x[3]);
cdq(mid + 1,r);
}int main()
cdq(1,n);
int ans = 0;
for(int i = 1;i <= n;++i) ans = max(ans,a[i].ans);
cout
}
BZOJ 2253 紙箱堆疊(CDQ分治)
description p 工廠是乙個生產紙箱的工廠。紙箱生產線在人工輸入三個引數 n p a 之後,即可自動化生產三邊邊長為 a mod p,a 2 mod p,a 3 mod p a 4 mod p,a 5 mod p,a 6 mod p a 3n 2 mod p,a 3n 1 mod p,a ...
BZOJ2253 紙箱堆疊 CDQ分治
time limit 30 sec memory limit 256 mb submit status discuss p 工廠是乙個生產紙箱的工廠。紙箱生產線在人工輸入三個引數 n p a 之後即可自動化生產三邊邊長為 a mod p,a 2 mod p,a 3 mod p a 4 mod p,a...
bzoj1078 斜堆 推理
orz 大意就是證明了當前的斜堆中沿著只有左子樹的那條鏈的頂端是當前堆中最後加入的。特殊情況該節點的子節點是葉節點,則取葉節點。然後倒推即可,注意最後要加乙個空格!因為這個pe了一遍 include include include define n 205 using namespace std i...