玲瓏OJ 1129 - 喵哈哈村的戰鬥魔法師丶壞壞い月
阿新 • • 發佈:2017-05-31
min return itl ati data- mar names 題解 記錄
1129 - 喵哈哈村的戰鬥魔法師丶壞壞い月
常見的數據結構中,我們選擇使用分塊來處理這道題。
我們將n個數,分成sqrt(n)塊,每塊裏面的元素最多有sqrt(n)個元素。對於每一個塊,我們維護Upd[i]表示這個塊整個增加了多少,Max[i]表示這個塊內的最大值是多少。
對於查詢和更新,如果完全囊括了塊的話,我們就只對Upd[i]和Max[i]進行更新,否則的話,我們就暴力更新這個塊的元素即可。
總體復雜度O(n*根號n) Upd相當於一個標記,只起到記錄的作用,兩端暴力更新~
Time Limit:3s Memory Limit:256MByte
Submissions:315Solved:71
DESCRIPTION壞壞い月是月大叔的ID,他是一個掌握者772002種魔法的物理系戰士,最擅長的技能就是搞事。今天他又要開始搞事了。
給你n
個數,你需要實現一下操作:
-
l r v ,在[l,r]區間內找到第一個大於等於v的數,輸出這個數的下標,如果找不到的話,請輸出-1噢
-
l r v,讓[l,r]區間所有數增加v
,表示有t組數據 對於每組數據: 第一行包含兩個整數 n(1≤n≤100000),q(1≤q≤100000),表示數的個數,以及詢問的個數。 第二行包含n個整數 ai(1≤ai≤1000000000) 接下來q行,每行四個整數opt(1≤opt≤2),l,r(1≤l≤r≤n),v(1≤v≤1000000000)
常見的數據結構中,我們選擇使用分塊來處理這道題。
我們將n個數,分成sqrt(n)塊,每塊裏面的元素最多有sqrt(n)個元素。對於每一個塊,我們維護Upd[i]表示這個塊整個增加了多少,Max[i]表示這個塊內的最大值是多少。
對於查詢和更新,如果完全囊括了塊的話,我們就只對Upd[i]和Max[i]進行更新,否則的話,我們就暴力更新這個塊的元素即可。
總體復雜度O(n*根號n) Upd相當於一個標記,只起到記錄的作用,兩端暴力更新~
#include <iostream> #include<cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; const int N = 100000; int n,m; LL a[N],Max[N],Upd[N]; int pos[N]; int block = 0; void reset(int x) { int l=(x-1)*block+1,r=min(x*block,n); for(int i=l; i<=r; i++) Max[x]=max(Max[x],a[i]); } void update(int x,int y,LL v) { if(pos[x]==pos[y]) { for(int i=x; i<=y; i++)a[i]=a[i]+v; } else { for(int i=x; i<=pos[x]*block; i++)a[i]=a[i]+v; for(int i=(pos[y]-1)*block+1; i<=y; i++)a[i]=a[i]+v; } reset(pos[x]); reset(pos[y]); for(int i=pos[x]+1; i<pos[y]; i++) Upd[i]+=v; } int findidx(int x,LL v) { int l=(x-1)*block+1,r=min(x*block,n); for(int i=l; i<=r; i++) { if(a[i]+Upd[x]>=v) return i; } } int query(int x,int y,LL v) { if(pos[x]==pos[y]) { for(int i=x; i<=y; i++)if(a[i]+Upd[pos[i]]>=v) return i; } else { ///暴力找左邊 for(int i=x; i<=pos[x]*block; i++) if(a[i]+Upd[pos[i]]>=v) return i; ///分塊找中間 for(int i=pos[x]+1; i<pos[y]; i++) if(Max[i]+Upd[i]>=v) { return findidx(i,v); } ///暴力找右邊 for(int i=(pos[y]-1)*block+1; i<=y; i++) if(a[i]+Upd[pos[i]]>=v) return i; } return -1; } int main() { int T; scanf("%d",&T); while(T--) { memset(Max,0,sizeof(Max)); memset(Upd,0,sizeof(Upd)); scanf("%d%d",&n,&m); block = int(sqrt(n)); for(int i=1; i<=n; i++) { scanf("%lld",&a[i]); pos[i]=(i-1)/block+1; ///記錄每個元素屬於哪個塊 } int k; ///塊的個數 if(n%block)k=n/block+1; else k=n/block; for(int i=1; i<=k; i++) { reset(i); } while(m--) { int opt,l,r; LL v; scanf("%d%d%d%lld",&opt,&l,&r,&v); if(opt==1) { printf("%d\n",query(l,r,v)); } else { update(l,r,v); } } } return 0; }
玲瓏OJ 1129 - 喵哈哈村的戰鬥魔法師丶壞壞い月