COCI CONTEST #3 29.11.2014 KAMIONI
題目描述
A國的城市可以看做是數軸上的整數點,有n輛卡車在公路上往返行駛,它們只能在到達某個城市才能掉頭,掉頭是不需要時間的,而且卡車在途中不能停下來。這n輛卡車初始時可能位于不同的城市,在某個時刻它們同時出發,每輛卡車每分鐘可以到達下一個城市,即每分鐘可以行使單位1的路程。當卡車到達終點時,它將會進入時空隧道,瞬間消失。給出每輛卡車的行駛的路徑,即卡車的起點、中途每次掉頭的點及終點,有m次查詢,每次查詢指定兩輛卡車,問它們一共相遇多少次?
注意:卡車相遇點不一定是城市。另外,相遇時其中一輛卡車進入時光隧道不算相遇;起始瞬間兩輛卡車位于同一地點不算相遇;其中一輛卡車正好掉頭不算相遇。
n<=100000,m<100000,城市的編號在[1,10^9]之間。每輛卡車路徑掉頭的次數不超過3*10^5;所有卡車掉頭的總次數之和不超過3*10^5.
輸入:
第一行兩個整數n,m,表示卡車的數量和查詢的次數。
接下來n行,每行的第一個數為Ki(2<=Ki<=3*10^5),表示卡車的路徑包含Ki個點,接下來有Ki個數,每個數在區間[1,10^9]之間,按順序表示卡車行駛時經過的城市,包括起點和終點。
所有Ki之和超過3*10^5
接下來m行,每行兩個整數,表示查詢這兩輛卡車一共相遇多少次。
輸出:
對每次查詢,輸出一個整數,表示它們相遇次數。
50%的數據,n<100,Ki<1000,m<1000
思路:
首先我們應該將每一輛車的轉折點按照發生時間來排序。講每一個查詢都保存下來,當然重復的我們只留一個去計算,其余的我們應當保存在一個與保留的那一個有關的數據結構里。順便提一下,做這道題是一定要估計好空間復雜度,防止被卡空間。然后在保存一個詢問的時候只保存在拐點少的那個的名下。然后枚舉每一個拐點就可以了。
然后我們分析時間復雜度:
如果某個卡車的轉折點小于k√個,即使和它名下存的查詢關系多于k√個,但是它在轉折點數組中的出現次數一定小于k√次。
如果某個卡車的轉折點多于k√個,即使它在轉折點一定枚舉k√+次,但是和它有查詢關系的卡車一定小于k√個。
通過以上分析,我們知道均攤的時間復雜度不會超過k√個。所以總的時間復雜度就是O(k32).
代碼:(用hash表實現去重以及保存詢問)
#include<algorithm> #include<map> #include<cstdio> #include<vector> #define LL long long #define PII pair<int, int> const int MAXN = 300010; using namespace std; struct event {int id, p, dir; //id->trucks' number; p->position; dir->directionLL time;bool operator < (const event &rhs) const{if(time != rhs.time) return time < rhs.time;return dir > rhs.dir;}event(){}event(int a, int b, int c, LL d){id = a, p = b, dir = c; time = d;} }; int h[2000000]; PII hsh[2000000]; int hshit(PII t) {int p = 1LL * (t.second - t.first) * t.first * 12580 % 2000000;while(h[p] && hsh[p] != t) p = (p + 1) % 2000000;++ h[p];hsh[p] = t;return p; } struct query {int id, was_left, qid;query() {}query(int a, int b, int c) { id = a; was_left = b; qid = c; } }; struct List {int id, num;vector<int> index;List *next;List(){next = NULL; id = num = -1;} }*Adj[MAXN], *hs[2000000]; struct truck {int k, p, dir;LL time;vector<query> queries; } trucks[MAXN]; inline void GET(int &n) {n = 0; char c;do c = getchar(); while(c > '9' || c < '0');while(c >= '0' && c <= '9') {n = n*10 + c - '0'; c = getchar();} } int n, m; void init(event &e) {trucks[e.id].p = e.p;trucks[e.id].dir = e.dir;trucks[e.id].time = e.time; } int check(const truck &a, const truck &b, LL pretime, int predir) {if (!b.dir && pretime >= b.time)return 0;int b_pos, a_pos;if (!b.dir){b_pos = b.p;a_pos = (a.time - b.time) *(-predir) + a.p;}else{a_pos = a.p;b_pos = (a.time - b.time) * b.dir + b.p;}return b_pos < a_pos ? -1 : 1; } int ans[MAXN]; void solve(const truck &t, query &q, LL pretime, int predir) {int is_left = check(t, trucks[q.id], pretime, predir);ans[q.qid] += (q.was_left * is_left == -1);q.was_left = is_left; } int main() {vector<event> events;GET(n); GET(m);int x, newx;LL tsum;event e;for(int i = 0; i < n; ++ i){tsum = 0;GET(trucks[i].k); GET(x);for(int j = 0; j < trucks[i].k - 1; ++ j){GET(newx);e = event(i, x, x < newx ? 1 : -1, tsum);if(!j) init(e);else events.push_back(e);tsum += abs(x - newx);x = newx;}e = event(i, x, 0, tsum);events.push_back(e);}int a, b;for(int i = 0; i < m; i ++){GET(a); GET(b);-- a; -- b;if(a > b) swap(a, b);int t = hshit(PII(a, b));if(h[t] > 1) {hs[t]->num ++;hs[t]->index.push_back(i);continue;}else {if(!Adj[a]) {Adj[a] = new List();Adj[a]->num = 1;Adj[a]->id = b;hs[t] = Adj[a];hs[t]->index.push_back(i);}else {List *p = new List();p->next = Adj[a]->next;p->id = b;p->num = 1;Adj[a]->next = p;hs[t] = p;hs[t]->index.push_back(i);}}if (trucks[a].k > trucks[b].k) swap(a, b);trucks[a].queries.push_back(query(b, trucks[b].p < trucks[a].p ? -1 : 1, i));}sort(events.begin(), events.end());for(int i = 0; i < events.size(); i ++){e = events[i];LL prev_time = trucks[e.id].time;int prev_dir = trucks[e.id].dir;init(e);for(int i = 0; i < trucks[e.id].queries.size(); i ++){query &q = trucks[e.id].queries[i];solve(trucks[e.id], q, prev_time, prev_dir);}}int sz;for(int i = 0; i < n; i ++)for(List *p = Adj[i]; p; p = p->next) {sz = p->index.size();for(int j = 1; j < sz; j ++)ans[p->index[j]] = ans[p->index[0]];}for(int i = 0; i < m; ++i)printf("%d\n", ans[i]);return 0; }轉載于:https://www.cnblogs.com/geng4512/p/5296911.html
總結
以上是生活随笔為你收集整理的COCI CONTEST #3 29.11.2014 KAMIONI的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Quick-Cocos2d-x初学者游戏
- 下一篇: StringFormat