Luogu P1533 可憐的狗狗
阿新 • • 發佈:2018-12-20
題目背景
小卡由於公務需要出差,將新家中的狗狗們託付給朋友嘉嘉,但是嘉嘉是一個很懶的人,他才沒那麼多時間幫小卡喂狗狗。
題目描述
小卡家有N只狗,由於品種、年齡不同,每一隻狗都有一個不同的漂亮值。漂亮值與漂亮的程度成反比(漂亮值越低越漂亮),吃飯時,狗狗們會按順序站成一排等著主人給食物。
可是嘉嘉真的很懶,他才不肯喂這麼多狗呢,這多浪費時間啊,於是他每次就只給第i只到第j只狗中第k漂亮的狗狗餵食(好狠心的人啊)。而且為了保證某一隻狗狗不會被喂太多次,他喂的每個區間(i,j)不互相包含。
輸入輸出格式
輸入格式:
第一行輸入兩個數n,m,你可以假設n<300001 並且 m<50001;m表示他餵了m次。
第二行n個整數,表示第i只狗的漂亮值為ai。
接下來m行,每行3個整數i,j,k表示這次餵食喂第i到第j只狗中第k漂亮的狗的漂亮值。
輸出格式:
M行,每行一個整數,表示每一次喂的那隻狗漂亮值為多少。
輸入輸出樣例
輸入樣例#1: 複製
7 2 1 5 2 6 3 7 4 1 5 3 2 7 1
輸出樣例#1: 複製
3 2
裸的平衡樹(可惜菜雞不會)
先要離散化
因為區間互不包含,所以若l是單調遞增,r也一定單調遞增,所以果斷排序
排序後用佇列維護選的數,要從中選取第K大的,權值樹狀陣列上二分,好寫有跑的快
nlg n lg n
菜雞之前因為沒有記q陣列的id,並且忘了離散化後答案要是原來的答案不能是離散化後的答案,樣例也忒水了
而WA了一次,
#include<cstdio> #include<algorithm> using namespace std; int read() { int ret=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') ret=(ret<<1)+(ret<<3)+ch-'0',ch=getchar(); return ret; } const int N=1e6+4; int n,m,b[N],l,r,mid,ans[N],s,ll,rr,bb[N]; struct A{ int id,x; }a[N]; struct B{ int id,l,r,k; }q[N]; bool cmp(A i,A j) { return i.x<j.x; } bool cmp1(B i,B j) { return i.l<j.l; } struct C { int c[N]; inline void add(int x,int k) { for(int i=x;i<=n;i+=i&-i) c[i]+=k; } inline int sum(int x) { int ret=0; for(int i=x;i;i-=i&-i) ret+=c[i]; return ret; } }tree; int main() { n=read(),m=read(); for(int i=1;i<=n;i++) a[i]=(A){i,read()}; sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++) b[a[i].id]=i,bb[i]=a[i].x; for(int i=1;i<=m;i++) q[i]=(B){i,read(),read(),read()}; sort(q+1,q+m+1,cmp1); ll=1,rr=0; for(int i=1;i<=m;i++) { while(rr<q[i].r) rr++,tree.add(b[rr],1); while(ll<q[i].l) tree.add(b[ll],-1),ll++; l=1,r=n; while(l<=r) { mid=l+r>>1; if(tree.sum(mid)>q[i].k) r=mid-1; else if(tree.sum(mid)<q[i].k) l=mid+1; else s=mid,r=mid-1; } ans[q[i].id]=bb[s]; } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }