Vijos1448题解---线段树+括号法
生活随笔
收集整理的這篇文章主要介紹了
Vijos1448题解---线段树+括号法
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
描述
校門外有很多樹,有蘋果樹,香蕉樹,有會扔石頭的,有可以吃掉補充體力的……
如今學校決定在某個時刻在某一段種上一種樹,保證任一時刻不會出現(xiàn)兩段相同種類的樹,現(xiàn)有兩個操作:
K=1,K=1,讀入l、r表示在區(qū)間[l,r]中種上一種樹,每次操作種的樹的種類都不同
K=2,讀入l,r表示詢問l~r之間能見到多少種樹(l,r>0)
輸入格式
第一行n,m表示道路總長為n,共有m個操作
接下來m行為m個操作
輸出格式
對于每個k=2輸出一個答案
樣例輸入5 4
1 1 3
2 2 5
1 2 4
2 3 5
樣例輸出
1 2 普通的暴力算法,植樹的時間為O(n),查詢的時間也為O(n),所以總體的時間復雜度為O(nm)。 這里介紹一種獨特的想法---括號法。 在植樹區(qū)間的左端點放一個左括號“(”,右端點放一個右括號“)”,使得植樹時間為O(1)。 顯而易見,查詢的結(jié)果為右端點左邊“(”的個數(shù)減去左端點左邊“)”的個數(shù),時間為O(n)。 2至5之間有2-1=1種樹。 3至5之間有2-0=2種樹。 為了進一步優(yōu)化時間復雜度,我們使用線段樹維護左右括號的數(shù)量,使時間降到log級。 獻上代碼: 1 #include <cstdio> 2 int n,m; 3 struct node 4 { 5 int x,y; 6 int a[3];//a[1]表示左括號的數(shù)量,a[2]表示右括號的數(shù)量。 7 }t[300002]; 8 void init(int k,int l,int r)//初始化。 9 { 10 t[k].x=l; 11 t[k].y=r; 12 if(l==r)return; 13 int mid=(l+r)/2; 14 init(2*k,l,mid); 15 init(2*k+1,mid+1,r); 16 } 17 void build(int k,int l,int op) 18 { 19 if(t[k].x<=l&&l<=t[k].y)//若在當前節(jié)點的范圍內(nèi),括號數(shù)量加1。 20 t[k].a[op]++; 21 if(t[k].x==t[k].y)return; 22 int mid=(t[k].x+t[k].y)/2; 23 if(l<=mid)build(2*k,l,op);//查詢左兒子。 24 if(l>=mid+1)build(2*k+1,l,op);//查詢右兒子。 25 } 26 int find(int k,int l,int r,int op)//查找l到r內(nèi)括號的個數(shù)。 27 { 28 int ans=0; 29 if(l<=t[k].x&&t[k].y<=r)return t[k].a[op]; 30 int mid=(t[k].x+t[k].y)/2; 31 if(l<=mid)ans+=find(2*k,l,r,op); 32 if(r>=mid+1)ans+=find(2*k+1,l,r,op); 33 return ans; 34 } 35 int main() 36 { 37 int k,l,r,ans1,ans2; 38 scanf("%d%d",&n,&m); 39 init(1,1,n); 40 for(int i=1;i<=m;i++) 41 { 42 scanf("%d%d%d",&k,&l,&r); 43 if(k==1) 44 { 45 build(1,l,1); 46 build(1,r,2); 47 } 48 if(k==2) 49 { 50 ans1=ans2=0; 51 ans1=find(1,1,r,1); 52 if(l-1>=1)ans2=find(1,1,l-1,2); 53 printf("%d\n",ans1-ans2); 54 } 55 } 56 return 0; 57 }轉(zhuǎn)載于:https://www.cnblogs.com/c0per/p/5775043.html
總結(jié)
以上是生活随笔為你收集整理的Vijos1448题解---线段树+括号法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [图解tensorflow源码] [原创
- 下一篇: 折中算法