这算是之前的旧文章了,现在不这么记了
之前做的题比较少,也没有怎么整理,但是现在不同往日了。在不出点成绩就要退役了,QwQ,AFO
在上者中寻找最长连续有序序列长度
P1434 [SHOI2002]
滑雪
题目描述
Michael
喜欢滑雪。这并不奇怪,因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael
想知道在一个区域中最长的滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子:
1 2 3 4 5
| 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9
|
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度会减小。在上面的例子中,一条可行的滑坡为
\(24\)-\(17\)-\(16\)-\(1\)(从 \(24\) 开始,在 \(1\) 结束)。当然 \(25\)-\(24\)-\(23\)-\(\ldots\)-\(3\)-\(2\)-\(1\)
更长。事实上,这是最长的一条。
输入格式
输入的第一行为表示区域的二维数组的行数 \(R\) 和列数 \(C\)。下面是 \(R\) 行,每行有 \(C\) 个数,代表高度(两个数字之间用 \(1\) 个空格间隔)。
输出格式
输出区域中最长滑坡的长度。
样例 #1
样例输入 #1
1 2 3 4 5 6
| 5 5 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9
|
样例输出 #1
提示
对于 \(100\%\) 的数据,\(1\leq R,C\leq 100\)。
![]()
开始的时候写错了,写了个伪代码,然后过来6个点,
(什么水数据)
这个是记忆化搜索实现的,思想可以迁移……嗯,学习学习
code
QwQ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include <bits/stdc++.h> using namespace std; int n, m, ans = 0; int MAP[105][105]; int f[205][205] = {0}, temp; int xx[4] = {1, -1, 0, 0}, yy[4] = {0, 0, -1, 1}; int search(int x, int y) { if (f[x][y])return f[x][y]; f[x][y] = 1; for (int i = 0; i < 4; i++) { if ((x + xx[i] > 0) && (y + yy[i] > 0) && (x + xx[i] <= n) && (y + yy[i] <= m)) { if (MAP[x][y] < MAP[x + xx[i]][y + yy[i]]) { search(x + xx[i], y + yy[i]); f[x][y] = max(f[x][y], f[x + xx[i]][y + yy[i]] + 1); } } } return f[x][y]; } int main() { freopen("in.txt", "r", stdin); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { scanf("%d", &MAP[i][j]); } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { temp = search(i, j); ans = max(ans, temp); } } printf("%d\n", ans); return 0; }
|
偏序序列在线序列中项
P1168 中位数
题目描述
给出一个长度为\(N\)的非负整数序列\(A_i\),对于所有\(1 ≤ k ≤ (N + 1) / 2\),输出\(A_1, A_1 \sim A_3, …,A_1 \sim A_{2k -
1}\)的中位数。即前\(1,3,5,…\)个数的中位数。
输入格式
第\(1\)行为一个正整数\(N\),表示了序列长度。
第\(2\)行包含\(N\)个非负整数\(A_i (A_i ≤ 10^9)\)。
输出格式
共\((N + 1) / 2\)行,第\(i\)行为\(A_1,
A_3, …, A_{2k - 1}\)的中位数。
样例 #1
样例输入 #1
样例输出 #1
## 提示
对于\(20\%\)的数据,\(N ≤ 100\);
对于\(40\%\)的数据,\(N ≤ 3000\);
对于\(100\%\)的数据,\(N ≤ 100000\)。
这道题上各位大佬也是各显神通的,有的用两个堆性质运用到极致的(其实就是优先队列
有的用vector加lower_bound的也也可以过
更有人直接暴力sort,当然TLE就是了,嘿嘿
==第一种==
的思想很明确,先建两个优先队列,一个大根堆,一个小根堆,再加一个中项mid,中项前在大根堆,后在小根堆,这样把这两个优先队列夹着个mid一合并就是序列了。
然后就是愉快向里面填数了(根据中项判断)。符合条件(为奇数个数时)时输出中项mid即可,输出前检查mid是否正确(根据堆的性质和中项的性质,两边堆的元素个数大小不相等的时候,多的向通过mid向少的转移,因为输出是奇数个数,所以和上mid,两边堆的元素个数是可以相等的!)
最后就愉快的输出mid了,嘿嘿嘿 ヾ(≧▽≦*)o
==第二种==的找到待插入的数正确偏序位置,插入,简单粗暴,效率奇高
==第三种==是比较难写的树状数组写法,都是标签的锅QwQ然而什么权值线段树,树上找第K小什么的我还不会啦,等会了,再来看吧
### code
1.优先队列解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include<bits/stdc++.h> #include<queue> using namespace std; int n; int a[100100]; int mid,temp; priority_queue<int,vector<int>,less<int> >q1; priority_queue<int,vector<int>,greater<int> >q2; int main(){ scanf("%d",&n); scanf("%d",&temp); mid=temp; printf("%d",temp); for(int i=2;i<=n;i++){ scanf("%d",&temp); if(temp>mid) q2.push(temp); else q1.push(temp); if(i%2==1){ while(q1.size()!=q2.size()){ if(q1.size()>q2.size()){ q2.push(mid); mid=q1.top(); q1.pop(); } else{ q1.push(mid); mid=q2.top(); q2.pop(); } } cout<<mid<<endl; } } return 0; }
|
2.vector直接插入法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| #include <bits/stdc++.h> using namespace std; int n; vector<int>a; int main() { cin>>n; for(int i=1,x;i<=n;i++) { scanf("%d",&x); a.insert(upper_bound(a.begin(),a.end(),x),x); if(i%2==1) { printf("%d\n",a[(i-1)/2]); } } return 0; }
|
3.在树状数组上找第k小法==权值树状数组==
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include<iostream> #include<cstdio> #include<algorithm> using namespace std;
int n,tot; const int maxn=1e5+10; int bit[maxn]; int a[maxn],b[maxn];
inline int lowbit(int x) { return x&-x; } inline void add(int pos,int x) { for(int i=pos;i<=tot;i+=lowbit(i))bit[i]+=x; } inline int find_kth(int k) { int ans=0,now=0; for(int i=20;i>=0;i--) { ans+=(1<<i); if(ans>tot||now+bit[ans]>=k)ans-=(1<<i); else now+=bit[ans]; } return ans+1; }
int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[++tot]); b[tot]=a[tot]; } sort(a+1,a+1+n); tot=unique(a+1,a+1+tot)-a-1; for(int i=1;i<=n;i++)b[i]=lower_bound(a+1,a+1+tot,b[i])-a; for(int i=1;i<=n;i++) { add(b[i],1); if(i&1)printf("%d\n",a[find_kth((i+1)>>1)]); } return 0; }
|
🍂暂时结束,不再更新↩︎