Codeforces Round #207 (Div. 1) A. Knight Tournament
Title:
-
n Knights (No. 1-n), with m battles, ensure that the number of each battle is > = 2. Give the information of M battles: the information of each battle is: give an interval [l, r], and then give a winner number won of the battle, which means that the knights who have not been defeated in [l, r] will be defeated by won in this battle. Ask, output 1-n each knight is defeated by which knight, among them win the final victory Knight output 0.
Train of thought:
-
At first, I wanted to use set, but I immediately rejected this idea (I think it must be T, and I didn'T really figure out how to deal with it. Later it was done with set, but it is impossible to pass without Baidu. It will not traverse the set and iterator will not be used. ps: anyway, I haven'T learned c++, www)
The first code idea:
Line tree offline query algorithm. Save all the information first. Then reverse the order and cover it back (it's obviously a little weird if the order is positive, because the Knights included in the interval are not all defeated, so if the order is positive, the later update should also record the knights that have been defeated before, please). If it is covered in reverse order, the final result will not be affected.
So this problem is to update the values of all points in an interval to the same won, but in fact, the interval does not maintain anything. So I was a little confused at the beginning, I didn't know what to maintain with line tree. Finally, I think that interval value has no practical significance and can not be used, so it's better to sum it simply. And then I started to write.
After writing the first code, WA 7, (I don't like to make samples, so debug ging is a very self tormenting process www don't know what's wrong), I still made the first sample under the code. No pushdown was found when query was found. [but I don't know why the disabled hand doubled the array of lazy, which was still quadrupled, and then I don't know why something drove me to delete it]
Then I handed in the second code, WA 11, and I didn't know where I was wrong.
It's true that I tried many samples (because they are very simple www). Then I tried the second sample under the code and found that I couldn't run out. Then it was adjusted, and it was discovered that int was exploded. 3e5*3e5 must have burst qaq, so it changed long long to all data types, and then passed third codes.
Realization of line tree
Initialization is 0, of course. It's winner. That is to say, each node of segment tree is 0. The intervals given by our reverse update are all corresponding won. The final answer is to update all intervals to the value of a single node.
//514ms #include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define INF 0x3f3f3f3f #define lowbit(x) x & (-x) #define MID ((l + r ) >> 1 ) #define lsn rt << 1 #define rsn rt << 1 | 1 #define Lson lsn, l, mid #define Rson rsn, mid + 1, r #define QL Lson, ql, qr #define QR Rson, ql, qr using namespace std; typedef long long ll; typedef unsigned long long ull; const ll maxN = 3e5 + 5; ll n, m; struct node{ ll s, e, won; node(ll a = 0, ll b = 0, ll c = 0) : s(a), e(b), won(c) {} }info[maxN]; ll tree[maxN << 2], lazy[maxN << 2]; void init() { memset(lazy, 0, sizeof(lazy)); } void pushup(ll rt) { tree[rt] = tree[lsn] + tree[rsn]; return; } void pushdown(ll rt, ll l, ll r) { if(lazy[rt] != 0) { ll mid = MID; tree[lsn] = lazy[rt] * (mid - l + 1); tree[rsn] = lazy[rt] * (r - mid); lazy[lsn] = lazy[rt]; lazy[rsn] = lazy[rt]; lazy[rt] = 0; } } void build_tree(ll rt, ll l, ll r) { if(l == r) { tree[rt] = 0; return ;} ll mid = MID; build_tree(Lson); build_tree(Rson); pushup(rt); } void updata_range(ll rt, ll l, ll r, ll ql, ll qr, ll val) { if(ql <= l && qr >= r) { tree[rt] = val * (r - l + 1); lazy[rt] = val; return; } pushdown(rt, l, r); ll mid = MID; if(qr <= mid) updata_range(QL, val); else if(ql > mid) updata_range(QR, val); else { updata_range(QL, val); updata_range(QR, val); } pushup(rt); } ll query(ll rt, ll l, ll r, ll dot) { if(l == r) return tree[rt]; pushdown(rt, l, r); ll mid = MID; if(dot <= mid) return query(Lson, dot); else if(dot > mid) return query(Rson, dot); } int main() { while(~scanf("%lld%lld", &n, &m)) { init(); for(ll i = 1; i <= m; i ++ ) scanf("%lld%lld%lld", &info[i].s, &info[i].e, &info[i].won); build_tree(1, 1, n); for(ll i = m; i > 0; i -- ) { if(info[i].s <= info[i].won - 1) updata_range(1, 1, n, info[i].s, info[i].won - 1, info[i].won); if(info[i].won + 1 <= info[i].e) updata_range(1, 1, n, info[i].won + 1, info[i].e, info[i].won); } for(ll i = 1; i <= n; i ++ ) printf("%lld%c", query(1, 1, n, i), " \n"[i == n]); } return 0; } /* 8 1 1 8 8 */ /* 300000 10 1 10 1 1 100 1 1 1000 1 1 10000 1 1 100000 1 1 200000 1 1 200020 1 1 200700 1 1 299999 1 1 300000 300000 */
The next two are set methods. It's fast, O(n).
The idea is to insert all 1-n into the set. Then every time you enter an interval, erase the value of the entire interval, and save ans[] = won. After that, insert won into set. Until all the intervals are completed, the remaining one in the set is the final winner, whose ans [] is set to 0
In addition to the use of iterators, there is a weird use of erase.
-
If erase points to an it content, then the iterator is also deleted. So save it before you delete it. Of course, the simple and tall processing is st.erase(iter + +);
-
Another process is that iter = st.erase(iter);. After deleting the content pointed by iter, it will point to the address of the next element. So you can directly update the location of the iter to the address of the next element.
-
The iterator of vector is different from this. For vector, after deleting an element, the next element will move to the original position of the deleted element, that is, the iter will not change.
//343ms #include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define INF 0x3f3f3f3f #define lowbit(x) x & (-x) #define MID ((l + r ) >> 1 ) #define lsn rt << 1 #define rsn rt << 1 | 1 #define Lson lsn, l, mid #define Rson rsn, mid + 1, r #define QL Lson, ql, qr #define QR Rson, ql, qr using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxN = 3e5 + 5; int n, m; int ans[maxN]; int main() { while(~scanf("%d%d", &n, &m)) { memset(ans, 0, sizeof(ans)); set<int>st; set<int>::iterator iter; for(int i = 1; i <= n; i ++ ) st.insert(i); for(int i = 1; i <= m; i ++ ) { int l, r, won; scanf("%d%d%d", &l, &r, &won); iter = st.lower_bound(l); while(iter != st.end() && *iter <= r) { ans[*iter] = won; iter = st.erase(iter);//Where to point to the next element after deleting an element //st.erase(iter + +); also available. Explanation: after deleting the contents pointed by the iterator, the iter is deleted, so make a backup before deleting the pointer //If it is a vector, after deleting the element, the subsequent element will automatically move forward without moving the pointer, that is: vt.erase(it); } st.insert(won); } int won = *st.begin(); ans[won] = 0; for(int i = 1; i <= n; i ++ ) printf("%d%c", ans[i], " \n"[i == n]); } return 0; }
To avoid the weird change of the upper erase's iter, delete the interval directly. (I just know that interval can be deleted, tcl)
//358ms #include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define INF 0x3f3f3f3f #define lowbit(x) x & (-x) #define MID ((l + r ) >> 1 ) #define lsn rt << 1 #define rsn rt << 1 | 1 #define Lson lsn, l, mid #define Rson rsn, mid + 1, r #define QL Lson, ql, qr #define QR Rson, ql, qr using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxN = 3e5 + 5; int n, m; int ans[maxN]; int main() { while(~scanf("%d%d", &n, &m)) { memset(ans, 0, sizeof(ans)); set<int>st; set<int>::iterator iter; for(int i = 1; i <= n; i ++ ) st.insert(i); for(int i = 1; i <= m; i ++ ) { int l, r, won; scanf("%d%d%d", &l, &r, &won); iter = st.lower_bound(l); while(iter != st.end() && *iter <= r) { ans[*iter] = won; iter ++; } st.erase(st.lower_bound(l), iter); st.insert(won); } int won = *st.begin(); ans[won] = 0; for(int i = 1; i <= n; i ++ ) printf("%d%c", ans[i], " \n"[i == n]); } return 0; }