luogu題解 P2184 【貪婪大陸】
阿新 • • 發佈:2018-04-27
代碼 線段 https reg ID date spa 鏈接 href
- 題目鏈接:
https://www.luogu.org/problemnew/show/P2184
- 思路:
首先我想吐槽一下為什麽現有題解中的做法都是一樣的,而且還比較難以理解;
我就講下我的做法,本質上是一樣的,但是跟容易理解.
根據題意每加一次地雷就多一個種類對吧,我們用一個cnt記錄加過地雷的次數,同時分別用兩個數組記錄左右兩個端點的位置。然後查詢[l,r]時呢,我們分別查詢[1,l-1]有多少個右端點,[r+1,n]有多少個左端點,然後這兩個數的和是什麽意思呢?就是有多少次鋪地雷沒鋪到我們查詢的這個[l,r]區間。
最後cnt-剛剛兩次查詢的和就是有多少次地雷鋪到了[l,r]這個區間,輸出即可,當然,我們用線段樹維護這些操作。
- 代碼:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cctype> using namespace std; const int maxn=100005; int sum_r[maxn<<2],sum_l[maxn<<2],add[maxn<<2]; int n,m; int L,R; void update_l(int now,int l,int r,int t){ if(l==r){ sum_l[now]++; return ; } int mid=(l+r)>>1; if(t<=mid)update_l(now<<1,l,mid,t); else update_l(now<<1|1,mid+1,r,t); sum_l[now]=sum_l[now<<1]+sum_l[now<<1|1]; return ; } void update_r(int now,int l,int r,int t){ if(l==r){ sum_r[now]++; return ; } int mid=(l+r)>>1; if(t<=mid)update_r(now<<1,l,mid,t); else update_r(now<<1|1,mid+1,r,t); sum_r[now]=sum_r[now<<1]+sum_r[now<<1|1]; return ; } int query_l(int now,int l,int r){ if(L<=l&&r<=R){ return sum_l[now]; } int mid=(l+r)>>1; int ans=0; if(L<=mid)ans+=query_l(now<<1,l,mid); if(mid<R)ans+=query_l(now<<1|1,mid+1,r); return ans; } int query_r(int now,int l,int r){ if(L<=l&&r<=R){ return sum_r[now]; } int mid=(l+r)>>1; int ans=0; if(L<=mid)ans+=query_r(now<<1,l,mid); if(mid<R)ans+=query_r(now<<1|1,mid+1,r); return ans; } int main() { int op,l,r; int cnt=0,tmp=0; scanf("%d %d",&n,&m); for(register int i=1;i<=m;i++){ scanf("%d %d %d",&op,&l,&r); if(op==1){ update_l(1,1,n,l); update_r(1,1,n,r); cnt++; } else { L=r+1,R=n; if(L<=R)tmp+=query_l(1,1,n); L=1,R=l-1; if(L<=R)tmp+=query_r(1,1,n); cout<<cnt-tmp<<endl; tmp=0; } } return 0; }
luogu題解 P2184 【貪婪大陸】