所谓的日常 #9 - 除暴徒呂布助司徒 犯長安李倔聽賈詡

div.2

FZU 1492 地震预测

嗯,n * n的运行时间是不可以通过的...

事实上我们要对每个i,求出一个标号大于i且值小于A[i]的最大数,以及一个标号大于i且值大于A[i]的最小数。

那么将(A[i],i)这个二元组排序后得到数组B,然后维护一个标号单调递减的栈 来解决上面的两个问题。时间复杂度O(nlogn) (排序的复杂度)。

(>_<...嗯,这个题确实挂难了...起因是我把min看成了max,然后认为可以给大家做...不过还是有人通过了这个题好感动...恭喜@陈子民 同学 :) 

用std::set也可以很方便的通过这个题,不过需要更多的C++知识啦,这里先不实现了。

#include <stdio.h>
#include <algorithm>

const int N = 100000 + 5;
int n,A[N];
std::pair<int,int> B[N];
int stack[N],top;
int answer[N];

void solve() {
    top = 0;
    for (int i = 0; i < n; ++ i) {
        int id = B[i].second;
        while (top > 0 && stack[top - 1] < id) -- top;
        if (top > 0) {
            answer[id] = std::min(answer[id],std::abs(A[stack[top - 1]] - A[id]));
        }
        stack[top++] = id;
    }
}

long long work() {
    for (int i = 0; i < n; ++ i) {
        B[i] = std::make_pair(A[i],i);
    }
    std::sort(B,B + n);

    for (int i = 0; i < n; ++ i) {
        answer[i] = (int)1e7;
    }
    answer[n - 1] = A[n - 1];

    solve();
    std::reverse(B,B + n);
    solve();
    long long ret = 0;
    for (int i = 0; i < n; ++ i) {
        ret += answer[i];
    }
    return ret;
}

int main() {
    while (scanf("%d",&n) == 1) {
        for (int i = 0; i < n; ++ i) {
            scanf("%d",A + i);
        }
        printf("%I64d\n",work());
    }
}
View Code

 

div.1

FZU 2029 买票问题

去吧STL...

拎着一个set,一个map,以及一个queue,再加一个树状数组,就可以ac这个题了。时间复杂度(nlogn)。由于set/map的巨大常数,跑了2.7s。

STL的话,在这里可以看 link

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <map>
 4 #include <set>
 5 #include <queue>
 6 #include <algorithm>
 7 
 8 const int N = 100000 + 5;
 9 int n;
10 std::map<int,int> map;
11 std::set<std::pair<int,int> > set;
12 std::queue<int> que;
13 int A[N],B[N];
14 
15 struct Fenwick {
16     int C[N];
17 
18     void clear() {
19         std::fill(C,C + n,0);
20     }
21 
22     int modify(int p,int dt) {
23         for (int i = p; i < n; i += ~i & i + 1) C[i] += dt;
24     }
25 
26     int query(int p) {
27         int ret = 0;
28         for (int i = p; i >= 0; i -= ~i & i + 1) ret += C[i];
29         return ret;
30     }
31 } bit;
32 
33 int main() {
34     while (scanf("%d",&n) == 1) {
35         bit.clear();
36         map.clear();
37         set.clear();
38         while (!que.empty()) que.pop();
39 
40         for (int i = 0; i < n; ++ i) {
41             char str[13];
42             scanf("%s",str);
43             if (strcmp(str,"add") == 0) {
44                 int a,b;
45                 scanf("%d%d",&a,&b);
46                 A[i] = a;
47                 B[i] = b;
48                 map[a] = i;
49                 set.insert(std::make_pair(b,i));
50                 que.push(i);
51                 bit.modify(i,1);
52             } else if (strcmp(str,"pop") == 0) {
53                 while (!que.empty() && map.find(A[que.front()]) == map.end()) que.pop();
54                 if (!que.empty()) {
55                     int id = que.front(); que.pop();
56                     map.erase(A[id]);
57                     set.erase(std::make_pair(B[id],id));
58                     bit.modify(id,-1);
59                 }
60             } else if (strcmp(str,"leave") == 0) {
61                 if (!set.empty()) {
62                     int id = set.begin()->second;
63                     set.erase(set.begin());
64                     bit.modify(id,-1);
65                     map.erase(A[id]);
66                 }
67             } else {
68                 int x,y;
69                 scanf("%d%d",&x,&y);
70                 if (map.find(x) != map.end()) {
71                     int id = map[x];
72                     int cnt = bit.query(id - 1);
73                     printf("%d\n",cnt);
74                     if (cnt > y) {
75                         bit.modify(id,-1);
76                         map.erase(A[id]);
77                         set.erase(std::make_pair(B[id],id));
78                     }
79                 }
80             }
81         }
82     }
83 }
View Code

 

posted @ 2016-01-05 20:30  zstuACM  阅读(295)  评论(0编辑  收藏  举报