题目描述
给出一个长为 nn 的数列,以及 nn 个操作,操作涉及单点插入,单点询问,数据随机生成。
输入格式
第一行输入一个数字 nn。
第二行输入 nn 个数字,第 ii 个数字为 a_iai,以空格隔开。
接下来输入 nn 行询问,每行输入四个数字 mathrm{opt}opt、ll、rr、cc,以空格隔开。
若 mathrm{opt} = 0opt=0,表示在第 ll 个数字前插入数字 rr(cc 忽略)。
若 mathrm{opt} = 1opt=1,表示询问 a_rar 的值(ll 和 cc 忽略)。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 3
0 1 3 1
1 1 4 4
0 1 2 2
1 1 2 4
样例输出
2
3
数据范围与提示
对于 100\%100% 的数据,1 leq n leq 100000, -2^{31} leq mathrm{others}1≤n≤100000,−231≤others、mathrm{ans} leq 2^{31}-1ans≤231−1。
代码:
1 //#6282. 数列分块入门 6-单点插入,单点查询,数据随机生成 2 #include<bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 const int maxn=1e5+10; 6 7 int n,m; 8 int a[maxn*5],b[maxn],tag[maxn],pos[maxn]; 9 vector<int> vec[maxn]; 10 11 void rebuild() 12 { 13 memset(a,0,sizeof(a)); 14 int h=0; 15 for(int i=1;i<=m+1;i++){ 16 for(auto it:vec[i]){ 17 a[++h]=it; 18 } 19 vec[i].clear(); 20 } 21 m=sqrt(h); 22 for(int i=1;i<=h;i++) 23 pos[i]=(i-1)/m+1; 24 for(int i=1;i<=h;i++){ 25 vec[pos[i]].push_back(a[i]); 26 } 27 } 28 29 pair<int,int> find_pos(int r) 30 { 31 int i=1,cnt; 32 while(1){ 33 if(r>vec[i].size()){ 34 r-=vec[i].size(); 35 i++; 36 } 37 else{ 38 cnt=i; 39 break; 40 } 41 } 42 return make_pair(cnt,r); 43 } 44 45 void update(int l,int r) 46 { 47 pair<int,int> pr=find_pos(l); 48 vec[pr.first].insert(vec[pr.first].begin()+pr.second-1,r); 49 if(vec[pr.first].size()>3*m) rebuild(); 50 } 51 52 int query(int r) 53 { 54 pair<int,int> pr=find_pos(r); 55 return vec[pr.first][pr.second-1]; 56 } 57 58 int main() 59 { 60 scanf("%d",&n); 61 m=sqrt(n); 62 for(int i=1;i<=n;i++){ 63 scanf("%d",&a[i]); 64 pos[i]=(i-1)/m+1; 65 } 66 for(int i=1;i<=n;i++){ 67 vec[pos[i]].push_back(a[i]); 68 } 69 for(int i=1;i<=n;i++){ 70 int op,l,r,c; 71 scanf("%d%d%d%d",&op,&l,&r,&c); 72 if(op==0){ 73 update(l,r); 74 } 75 else{ 76 printf("%d ",query(r)); 77 } 78 } 79 return 0; 80 } 81 82 83 /* 84 10 85 1 3 4 2 5 7 11 3 5 1 86 0 1 5 1 87 1 1 7 2 88 0 3 9 1 89 1 4 8 7 90 1 1 10 6 91 1 3 5 3 92 1 5 9 7 93 1 6 12 6 94 1 2 7 4 95 1 3 4 5 96 97 7 98 7 99 3 100 4 101 11 102 1 103 5 104 3 105 */