Naive Operations
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 502768/502768 K (Java/Others)
Total Submission(s): 3636 Accepted Submission(s): 1612
Problem Description
In a galaxy far, far away, there are two integer sequence a and b of length n.
b is a static permutation of 1 to n. Initially a is filled with zeroes.
There are two kind of operations:
1. add l r: add one for al,al+1...ar
2. query l r: query ∑ri=l⌊ai/bi⌋
b is a static permutation of 1 to n. Initially a is filled with zeroes.
There are two kind of operations:
1. add l r: add one for al,al+1...ar
2. query l r: query ∑ri=l⌊ai/bi⌋
Input
There are multiple test cases, please read till the end of input file.
For each test case, in the first line, two integers n,q, representing the length of a,b and the number of queries.
In the second line, n integers separated by spaces, representing permutation b.
In the following q lines, each line is either in the form 'add l r' or 'query l r', representing an operation.
1≤n,q≤100000, 1≤l≤r≤n, there're no more than 5 test cases.
For each test case, in the first line, two integers n,q, representing the length of a,b and the number of queries.
In the second line, n integers separated by spaces, representing permutation b.
In the following q lines, each line is either in the form 'add l r' or 'query l r', representing an operation.
1≤n,q≤100000, 1≤l≤r≤n, there're no more than 5 test cases.
Output
Output the answer for each 'query', each one line.
Sample Input
5 12
1 5 2 4 3
add 1 4
query 1 4
add 2 5
query 2 5
add 3 5
query 1 5
add 2 4
query 1 4
add 2 5
query 2 5
add 2 2
query 1 5
Sample Output
1
1
2
4
4
6
题目大意:b[1-n] 是 1-n ,a[1-n] 是 0,add区间每一数加1,query区间a[i]/b[i]的和
思路:维护区间最小值,add操作为b[l]~b[r] 减一,最小值为0说明某个位置a[i]/b[i]=1, 答案贡献1,最后求区间和即可
1 #include <iostream> 2 #include <stdio.h> 3 #include <math.h> 4 #include <string.h> 5 #include <stdlib.h> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <algorithm> 12 #include <sstream> 13 #include <stack> 14 using namespace std; 15 #define rep(i,a,n) for (int i=a;i<n;i++) 16 #define per(i,a,n) for (int i=n-1;i>=a;i--) 17 #define pb push_back 18 #define mp make_pair 19 #define all(x) (x).begin(),(x).end() 20 #define fi first 21 #define se second 22 #define SZ(x) ((int)(x).size()) 23 #define FO freopen("in.txt", "r", stdin); 24 #define debug(x) cout << "&&" << x << "&&" << endl; 25 #define lowbit(x) (x&-x) 26 #define mem(a,b) memset(a, b, sizeof(a)); 27 typedef vector<int> VI; 28 typedef long long ll; 29 typedef pair<int,int> PII; 30 const ll mod=1000000007; 31 const int inf = 0x3f3f3f3f; 32 ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} 33 ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;} 34 //head 35 36 const int N=100010; 37 int b[N]; 38 int sum[N<<2],sub[N<<2],lazy[N<<2];//区间和 区间最小值 lazy标记 39 40 void Pushup(int rt) {//上传 41 sum[rt]=sum[rt<<1]+sum[rt<<1|1];//左右孩子之和 42 sub[rt]=min(sub[rt<<1],sub[rt<<1|1]);//左右孩子的最小值 43 } 44 45 void Pushdown(int rt) {//下压 46 lazy[rt<<1]+=lazy[rt];//传标记 47 lazy[rt<<1|1]+=lazy[rt]; 48 sub[rt<<1]-=lazy[rt];//更新 因为是每次减一 所以就直接减lazy 49 sub[rt<<1|1]-=lazy[rt]; 50 lazy[rt]=0;//清除父节点标记 51 } 52 53 void build(int rt,int L,int R) { 54 sum[rt]=0;//rt的初始状态 55 lazy[rt]=0; 56 if(L==R) { 57 scanf("%d",&b[L]);//建树的一种方式 58 sub[rt]=b[L]; 59 return; 60 } 61 int mid=(L+R)>>1;//递归建树 62 build(rt<<1,L,mid); 63 build(rt<<1|1,mid+1,R); 64 Pushup(rt);//因为不涉及修改,不需要下压,只需上传 65 } 66 67 void dfs(int rt,int L,int R) { 68 if(L==R) { 69 sum[rt]++; 70 sub[rt]=b[L]; 71 return; 72 } 73 int mid=(L+R)>>1; 74 Pushdown(rt); 75 if(!sub[rt<<1]) dfs(rt<<1,L,mid); 76 if(!sub[rt<<1|1]) dfs(rt<<1|1,mid+1,R); 77 Pushup(rt); 78 } 79 80 void Updata(int rt,int L,int R,int l,int r) {//L,R为时时变动的区间 81 if(L>=l&&R<=r) {//如果当前节点在待查询节点内 82 lazy[rt]++; 83 sub[rt]--; 84 if(!sub[rt]) dfs(rt,L,R);//如果区间最小值为0,递归搜索位置 85 return; 86 } 87 int mid=(L+R)>>1;//递归找l,r的涉及区间 88 Pushdown(rt);//需要走左右孩子,先下压 89 if(l<=mid) Updata(rt<<1,L,mid,l,r); 90 if(r>mid) Updata(rt<<1|1,mid+1,R,l,r); 91 Pushup(rt);//走完之后,状态上传给父亲节点 92 } 93 94 int Query(int rt,int L,int R,int l,int r) { 95 if(L>=l&&R<=r) //待查询区间内 96 return sum[rt]; 97 int mid=(L+R)>>1; 98 Pushdown(rt);//走左右孩子 99 int ans=0; 100 if(l<=mid) ans+=Query(rt<<1,L,mid,l,r); 101 if(r>mid) ans+=Query(rt<<1|1,mid+1,R,l,r); 102 Pushup(rt);//走完,状态上传给父亲节点 103 return ans; 104 } 105 106 107 int main() { 108 int n,q; 109 while(~scanf("%d%d",&n,&q)) { 110 build(1,1,n); 111 char s[10]; 112 int a,b; 113 while(q--) { 114 scanf("%s%d%d",s,&a,&b); 115 if(s[0]=='a') Updata(1,1,n,a,b); 116 else printf("%d ",Query(1,1,n,a,b)); 117 } 118 } 119 }
上面用了dfs搜索最小值为0的位置,也可以一直去找。
1 void Update(int L,int R,int l,int r,int rt) 2 { 3 if(a[rt]>1&&L<=l&&r<=R) 4 { 5 lazy[rt]++; 6 a[rt]--; 7 return; 8 } 9 if(a[rt]==1&&l==r) 10 { 11 sum[rt]++; 12 lazy[rt]=0; 13 a[rt]=b[l]; 14 return; 15 } 16 int mid=(l+r)>>1; 17 PushDown(rt); 18 if(L<=mid)Update(L,R,l,mid,rt<<1); 19 if(R>mid)Update(L,R,mid+1,r,rt<<1|1); 20 PushUp(rt); 21 }
!!!!这里的变量含义和第一个代码不一样。自行理解。