2019ICPC(上海) - Light bulbs(离散化+差分)
題目鏈接:點擊查看
題目大意:給出n個燈泡,初始化全都是熄滅狀態(tài),給出m次操作,每次操作給出閉區(qū)間[l,r],將該區(qū)間內(nèi)的燈泡狀態(tài)翻轉(zhuǎn),即熄滅的燈泡變?yōu)榇蜷_狀態(tài),打開的燈泡變?yōu)橄鐮顟B(tài),求最后打開燈泡的數(shù)量
題目分析:一開始想的是線段樹,寫到一半發(fā)現(xiàn)內(nèi)存開不下,然后就想樹狀數(shù)組,在開始重新返工之前又想到了簡單差分,于是抱著試一試的心態(tài)寫了一下,果不其然的T掉了,因為沒看清楚數(shù)據(jù)范圍。。雖然n是1e6,但是有1e3個數(shù)據(jù),一結合時間范圍就到了1e9,我又看到m很小,只有1e3,于是想從m出發(fā),如果只是對區(qū)間差分的話,那么所涉及的時間復雜度只有1e6,應該是沒問題的,這就涉及到離散化了,因為對于簡單差分,是[l,r]區(qū)間內(nèi)的book[l]++,book[r+1]--然后求前綴和來判斷的,所以在儲存區(qū)間端點的時候只需要儲存左區(qū)間l和右區(qū)間r+1即可,然后求前綴和時,我們需要找到一個前綴和為奇數(shù)的端點,操作為奇數(shù)時該點開始往后的點才是打開狀態(tài),記錄一下,然后等在找到一個前綴和為偶數(shù)的端點,這個時候之前記錄的端點到當前端點之間的燈泡全都是打開的,累加一下實際長度即可,然后記得清零之前標記的狀態(tài),如此往復遍歷一遍離散化后的端點即可,因為只要有一個區(qū)間端點+1,必定有一個區(qū)間端點-1,所以第一個區(qū)間端點的前綴和一定是奇數(shù),最后一個區(qū)間端點一定是偶數(shù),就不用考慮特殊情況了,上代碼:
蒟蒻的代碼:
#include<iostream> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e3+100;vector<int>v;struct Node {int l,r; }a[N];int getid(int x)//獲得離散化后的編號:getid(x) 獲得離散化前的數(shù)值:v[x],即v[getid(x)]=x; {return lower_bound(v.begin(),v.end(),x)-v.begin(); }int book[N*2];int main() {int w;cin>>w;int kase=0;while(w--){v.clear();int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=m;i++){scanf("%d%d",&a[i].l,&a[i].r);v.push_back(a[i].l);v.push_back(a[i].r+1);}sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());//離散化基操for(int i=0;i<v.size();i++)//差分數(shù)組book[i]=0;for(int i=1;i<=m;i++){int x,y;x=getid(a[i].l);y=getid(a[i].r+1);book[x]++;book[y]--;}int b=0;//前綴和int ans=0;//答案int flag=-1;//標記for(int i=0;i<v.size();i++){b+=book[i];if((b&1)&&flag==-1)//如果是當前階段第一個打開燈的狀態(tài),記錄一下端點{flag=i;}else if(!(b&1)&&flag!=-1)//如果已經(jīng)記錄過打開燈的端點,并且當前點為熄滅狀態(tài),求一下實際區(qū)間差并且清空狀態(tài){int x,y;x=v[flag];y=v[i];ans+=y-x;flag=-1;}}printf("Case #%d: %d\n",++kase,ans); } return 0; }題解的代碼:
#include <bits/stdc++.h> using namespace std;const int MAXN = 2010; pair<int, int> p[MAXN]; int main() {int T;int iCase = 0;int N, M;scanf("%d", &T);while (T--) {iCase++;scanf("%d%d", &N, &M);int tot = 0;while(M--) {int l, r;scanf("%d%d", &l, &r);p[tot++] = make_pair(l, 1);p[tot++] = make_pair(r+1, -1);}sort(p, p+tot);int now = 0;int ans = 0;int sum = 0;for (int i = 0; i < tot; i++) {if (now != p[i].first) {if (sum&1) ans += p[i].first - now;now = p[i].first;}sum += p[i].second;}if (sum &1) ans += N - now;printf("Case #%d: %d\n", iCase, ans);}return 0; }?
總結
以上是生活随笔為你收集整理的2019ICPC(上海) - Light bulbs(离散化+差分)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2019ICPC(沈阳) - Fish
- 下一篇: 2019ICPC(上海) - Count