SCOI2007 降雨量 [ST表]
阿新 • • 發佈:2017-12-29
register https 整數 tchar down pre lin body rmq
題面傳送門 biubiubiu
題目描述
我們常常會說這樣的話:“X年是自Y年以來降雨量最多的”。它的含義是X年的降雨量不超過Y年,且對於任意
Y<Z<X,Z年的降雨量嚴格小於X年。例如2002,2003,2004和2005年的降雨量分別為4920,5901,2832和
3890,則可以說“2005年是自2003年以來最多的”,但不能說“2005年是自2002年以來最多的”由於有些年份的降雨
量未知,有的說法是可能正確也可以不正確的。
輸入格式
輸入僅一行包含一個正整數n,為已知的數據。以下n行每行兩個整數yi和ri,為年份和降雨量,按照年份從小到大
排列,即yi
<water[y]是就是這種情況。
但是。。。該怎麽判斷一個區間內有沒有不知道的年份呀。。。
因為年份在輸入的時候就保證了一定是升序的,那麽如果x的編號-y的編號=x-y,就代表這個區間內沒有不知道
的。
然後剩下的再維護一下rmq就好了,但是我開始寫的線段樹不知道為什麽全MLE了,所以我用的是ST表。
Code
#include <bits/stdc++.h>
using namespace std;
const int max_n=50000+5;
const int inf=1e9;
int N,M;
int year[max_n],water[max_n];
inline int read()
{
register int x=0,v=1;
register char ch=getchar();
while(!isdigit(ch))
{
if(ch==‘-‘) v=-1;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<1)+(x<<3)+ch-‘0‘;
ch=getchar();
}
return x*v;
}
class ST
{
private:
int table[30][max_n],lg2[max_n];
public :
inline void build()
{
lg2[0]=-1;
for(register int i=1;i<=N;++i)
{
year[i]=read(),water[i]=table[0][i]=read();
lg2[i]=lg2[i>>1]+1;
}
for(register int i=1;i<=20;++i)
{
for(register int j=1;j+(1<<i)-1<=N;++j)
{
table[i][j]=max(table[i-1][j],table[i-1][j+(1<<i-1)]);
}
}
return;
}
inline int query(int l,int r)
{
if(l>r) return -inf;
int lg=lg2[r-l+1];
return max(table[lg][l],table[lg][r-(1<<lg)+1]);
}
};
inline int getw(int x)
{
int l=1,r=N,mid;
while(l<r)
{
mid=l+r>>1;
if(year[mid]>=x) r=mid;
else l=mid+1;
}
return l;
}
int main()
{
int x,y,idx,idy,jx,jy,t;
ST st;
N=read();
st.build();
M=read();
for(register int i=1;i<=M;++i)
{
x=read(),y=read();
idx=getw(x),idy=getw(y);
jx=(year[idx]==x),jy=(year[idy]==y);
t=st.query(idx+1,idy-1);
if(jx)
{
if(jy)
{
if(water[idx]<water[idy]) puts("false");
else if(t<water[idy])
{
if(y-x==idy-idx) puts("true");
else puts("maybe");
}
else puts("false");
}
else
{
if(t<water[idx]) puts("maybe");
else puts("false");
}
}
else
{
if(jy)
{
t=st.query(idx,idy-1);
if(t<water[idy]) puts("maybe");
else puts("false");
}
else puts("maybe");
}
}
return 0;
}
博主是蒟蒻,有錯誤請指出,謝謝!
SCOI2007 降雨量 [ST表]