天天看點

第五場周賽(字元串卡常個人Rank賽)——題解

本次題目因為比較簡單,除了個别題目,其餘題目我隻寫一個思路不再貼代碼。

先是Div.2的題解

A題奇怪的優化,把遞歸函數改成2*fun(...)即可,其實看懂程式也不難,就是求a*2b;

B題你會string嗎,直接String變量比較大小即可

C題數數,沒有卡正常方法,可以直接把數轉成二進制找1個數,此時複雜度為O(logN),更快的方法是使用__builtin_popcount函數,複雜度為O(m(m為數二進制中1的個數));

D,E題,看Div.1中本題解釋

所有代碼都可以10行内寫出,是以我不再給出代碼;

Div.1題解

A題簡單代碼優化,區間求和,直接再弄一個sum數組即可

B題簡單字元串處理,因為隻能在字元串尾部加字元,是以我的做法是把每個字元給個序号(既位置)存入容器,再分别做三個操作。

對于1操作,删除存儲那個字元的集合即可。

對于2操作,對應集合加上序号即可。

對于3操作,在1操作時候維護一個樹狀數組即可。

整體時間複雜度為O(QlogN),N為字元個數。但這種寫法常數略大,有更優化的思路可以和我探讨一下。

第五場周賽(字元串卡常個人Rank賽)——題解
第五場周賽(字元串卡常個人Rank賽)——題解

1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 set<int> dis[26];
 5 vector<pair<int,int>> vis(26,make_pair(0,0));
 6 int q,x,k,tot = 0;
 7 char ch;
 8 int c[100005] = {0};
 9 
10 inline int lowbit(int x){
11     return x&(-x);
12 }
13 
14 int update(int i){
15     while(i <= 100000){
16         c[i] += 1;
17         i += lowbit(i);
18     }
19 }
20 
21 int sum(int i){
22     int res = 0;
23     while(i > 0){
24         res += c[i];
25         i -= lowbit(i);
26     }
27     return res;
28 }
29 
30 int main(){
31     ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
32     freopen("test6.in","r",stdin);
33     freopen("test6.out","w",stdout);
34     int f1 = 0;
35     cin>>q;
36     generate(vis.begin(),vis.end(),[&f1](void)->pair<int,int>{return make_pair(f1++,0);});
37     while(q--){
38         cin>>x;
39         if(x == 1){
40             cin>>k;
41             if(k > 26)
42                 continue;
43             sort(vis.begin(),vis.end(),
44                 [](pair<int,int> a,pair<int,int> b)->bool{
45                     if(a.second == b.second)
46                         return a.first < b.first;
47                     return a.second > b.second;
48                 });
49             vis[k-1].second = 0;
50             for(auto it:dis[vis[k-1].first]){
51                 update(it);
52             }
53             dis[vis[k-1].first].clear();
54         }
55         else if(x == 2){
56             cin>>ch;
57             dis[ch-'a'].insert(++tot);
58             for(auto& a:vis){
59                 if(a.first == ch-'a'){
60                     a.second++;
61                     break;
62                 }
63             }
64         }
65         else if(x == 3){
66             cin>>ch;
67             if(dis[ch-'a'].empty())
68                 cout << -1 << endl;
69             else
70                 cout << *(dis[ch-'a'].begin())-sum(*(dis[ch-'a'].begin())) << endl;
71         }
72     }
73     cerr << clock() << endl;
74     return 0;
75 }      

View Code

C題簡單資訊檢索,标記初次出現位置即可

D題進階資訊檢索,把每個字首都存入map,此時可以使用unordered_map更快,或者建立Trie樹即可。好像還有人寫exKMP,也沒問題,畢竟100+100資料量。

E題密碼破解,馬拉車算法裸題。

繼續閱讀