前言
众所周知,有一类题目题意很简单,但是必须优化时间复杂度,在这里纪念几道题目(心累了,码了这么多天了自己的水平还是捉襟见肘),但是我还是不想放弃—真的我特别想把一件事坚持下去。
题意
给定一个序列a[ n ],对于任意元素i,我们定义c [ i ] 为i + 1到n的第一个比它大的值的位置与a[ i ]的位置之差,求和c [ i ] 数组
这道题虽然解法非常简单但是我把它想复杂了。实际上这道题目就是维护i之前的元素单调这一信息,就可以顺利解决。这就是优化复杂度的常见方法之一, 线性扫描的同时不忘维护信息。
#include<bits/stdc++.h>
#define maxn 100000
using namespace std;
int a[maxn],res = 0;
int main(){
int n;
stack<int> st;
cin >> n;
for(int i = 0; i < n; i++){
cin >> a[i];
if(!st.empty()){
while(!st.empty() && st.top() <= a[i])st.pop();
}
res += st.size();
st.push(a[i]);
}
cout << res <<endl;
return 0;
}
第二道题目相对来说复杂点,是LA 3905 这道题目。
这道题目如果单纯的模拟流星的运动轨迹是不足以解决这道题目的。这是因为第一如果说时间的单位不能用计算机来模拟,我们关心的实际上是每个流星进入相机框框的时间,所以可以预处理这一信息。然后还是在线性扫描的同时,不能说计算,必须还是要维护信息。
代码就不放出来了
还是特别丧
明明校赛的题目我可以解决的是 tarjan缩点还有单调栈这样的题目
但就是一直过不去。脑子一直在分散注意力状态中。明明多想一步就是DAG了但还是一直过不去,真心烦。我还想继续弄下去。真不知道以后这个会不会是0产出
#include<bits/stdc++.h>
#define maxn 100010
using namespace std;
struct Event{
double x;
int type;
bool operator < (const Event& a){
return x < a.x || (x==a.x && type > a.type);
}
} events[maxn*2];
void update(int x, int a, int w, double& L, double& R){
if(a == 0){
if(x <= 0 || x >= w) R = L-1;
}else if(a > 0){
L = max(L, -(double)x/a);
R = min(R, (double)(w-x)/a);
}else{
L = max(L, (double)(w-x)/a);
R = min(R, -(double)x/a);
}
}
int main(){
int T;
scanf("%d",&T);
while(T--){
int w,h,n;
scanf("%d%d%d", &w, &h, &n);
int e=0;
for(int i=0;i<n;i++){
int x, y, a, b;
scanf("%d%d%d%d", &x, &y, &a, &b);
double L = 0, R = 1e9;
update(x, a, w, L, R);
update(y, b, h, L, R);
if(R > L){
events[e++] = (Event){L, 0};
events[e++] = (Event){R, 1};
}
}
sort(events,events+e);
int cnt = 0, maxv = 0;
for(int i = 0; i < e; i++) {
int type = events[i].type;
if(type == 0) maxv = max(maxv, ++cnt);
else cnt--;
}
printf("%d\n", maxv);
}
return 0;
}
算了,有的时候不多想也是一种聪明,还是继续加油吧。