小易在维护数据的时候遇到一个需求,具体来说小易有一系列数据,这些数据了构成一个长度为n的数字序列,接下来小易会在这个序列上进行q次操作。
每次操作有一个查询的数字x,小易需要将序列数据中所有大于等于x的数字都减一,并输出在本次操作中有多少个数字被减一了。
小易犯了难,希望你能帮帮他。
第一行n,q,表示数字个数和操作个数。
接下来一行n个数表示初始的数字。
接下来q行,每行一个数,表示指定的数字x。,
对于每个询问,输出一个数字表示答案
4 3 1 2 3 4 4 3 1
1 2 4
3 2 1 2 3 3 3
1 0
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int N=2e5+5;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
int sum[N<<2],add[N<<2];
int a[N];
void pushUp(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
if(l==r)
{
sum[rt]=a[l];
return;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushUp(rt);
}
void pushDown(int rt,int ln,int rn)
{
if(add[rt])
{
add[rt<<1]+=add[rt];
add[rt<<1|1]+=add[rt];
sum[rt<<1]+=add[rt]*ln;
sum[rt<<1|1]+=add[rt]*rn;
add[rt]=0;
}
}
void update(int L,int R,int C,int l,int r,int rt)
{
if(L <= l && r <= R)
{
sum[rt]+=C*(r-l+1);
add[rt]+=C;
return ;
}
int m=(l+r)>>1;
pushDown(rt,m-l+1,r-m);
if(L <= m) update(L,R,C,l,m,rt<<1);
if(R > m) update(L,R,C,m+1,r,rt<<1|1);
pushUp(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L <= l && r <= R)
{
return sum[rt];
}
int m=(l+r)>>1;
pushDown(rt,m-l+1,r-m);
int ans=0;
if(L <= m) ans+=query(L,R,l,m,rt<<1);
if(R > m) ans+=query(L,R,m+1,r,rt<<1|1);
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
int n,q;
while(cin>>n>>q)
{
memset(add,0,sizeof(add));
for(int i=1; i<=n; i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
build(1,n,1);
while(q--)
{
int l=1,r=n,m,ans=-1,x;
cin>>x;
while(l<=r)
{
m=(l+r)>>1;
if(query(m,m,1,n,1)>=x)
{
r=m-1;
ans=m;
}
else
{
l=m+1;
}
}
if(ans==-1)
{
cout<<0<<endl;
}
else
{
cout<<n-ans+1<<endl;
update(ans,n,-1,1,n,1);
}
}
}
return 0;
}
n = list(map(int, input().split(' ')))
len = n[0]
N = n[1]
data = list(map(int, input().split(' ')))
while N:
N = N-1
num = 0
val = int(input())
for i in range(len):
if(data[i] >= val):
data[i] = data[i] - 1
num = num+1
print(num) c = input('数字个数和操作次数:')
d = c.split(' ')
n,q = int(d[0]),int(d[1])
a = input('请输入初始数:')
b = a.split(' ', n)
list1 = []
for i in b:
list1.append(int(i))
list2 = []
while q:
x = int(input('指定数字:'))
list2.append(x)
q -= 1
for k in list2:
list3 = []
count = 0
for j in list1:
if j >= k:
list3.append(j-1)
count += 1
else:
list3.append(j)
list1 = list3.copy()
print('有' + str(count) + '个数字被减一。') 我调试了好久,终于写出来了。
import java.util.Scanner;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), q = sc.nextInt();
int[] arr = new int[n];
for(int i = 0; i < n; i++) arr[i] = sc.nextInt();
Arrays.sort(arr); // 对数组按升序排列,防止之后每次查找都需要遍历一遍数组
// 开始q次减一操作
for(int i = 0; i < q; i++){
int opNum = sc.nextInt();
System.out.println(solve(arr, opNum));
}
}
private static int solve(int[] arr, int q) {
int count = 0;
// 从后往前遍历不会浪费查找
for(int i = arr.length - 1; i >= 0; i--){
if(arr[i] >= q){
arr[i] -= 1;
count ++;
}else
break; // 遇到小于q的数直接退出循环
}
return count;
}
} import sys b = []#b存储第三行及之后的数据 n,p = map(int,sys.stdin.readline().strip().split()) a = list(map(int,sys.stdin.readline().strip().split())) #a存储第二行数据 for i in range(p): b.append(int(sys.stdin.readline().strip())) for i in range(p): k = 0 for j in range(n): if a[j] >= b[i]: a[j] -= 1 k += 1 print(k)
# 好笨的方法,别笑话我,加油 n = int(input("n = ")) q = int(input("q = ")) list1 = [i for i in range(1,n+1)] for i in range(q): x = int(input("第" + str(i+1) + "次输入:")) num = 0 list2 = [] for c in list1: if c >= x: list2.append(c-1) num = num + 1 else: list2.append(c) print("本次操作中有{}个数被减一!".format(num)) list1 = list2.copy()
#include <bits/stdc++.h>
using namespace std;
class segtree{
public:
int n;
int* data;
int* tree;
int* lazy;
segtree(int* arr, int _n) : n(_n) {
data = new int[_n];
tree = new int[_n * 4];
lazy = new int[_n * 4];
fill_n(tree, _n * 4, 0);
fill_n(lazy, _n * 4, 0);
for (int i = 0; i < _n; i++) {
data[i] = arr[i];
}
build(0, 0, n - 1);
}
~segtree() {
delete []data;
delete []tree;
delete []lazy;
}
void push(int tId) {
tree[tId] = tree[tId * 2 + 1] + tree[tId * 2 + 2];
}
void pull(int tId, int l, int r) {
int mid = (l + r) / 2;
tree[tId * 2 + 1] += (mid - l + 1) * lazy[tId];
tree[tId * 2 + 2] += (r - mid) * lazy[tId];
lazy[tId * 2 + 1] += lazy[tId];
lazy[tId * 2 + 2] += lazy[tId];
lazy[tId] = 0;
}
void build(int tId, int l, int r) {
if (l == r) {
tree[tId] = data[l];
return;
}
int mid = (l + r) / 2;
build(tId * 2 + 1, l, mid);
build(tId * 2 + 2, mid + 1, r);
push(tId);
}
int get(int tId, int l, int r, int x) {
if (l == r && l == x) {
return tree[tId];
}
if (lazy[tId]) {
pull(tId, l, r);
}
int mid = (l + r) / 2;
if (x <= mid) {
return get(tId * 2 + 1, l, mid, x);
} else {
return get(tId * 2 + 2, mid + 1, r, x);
}
}
void modify(int tId, int l, int r, int ml, int mr, int v) {
if (ml <= l && r <= mr) {
tree[tId] += (r - l + 1) * v;
lazy[tId] += v;
return;
}
if (lazy[tId] != 0) {
pull(tId, l, r);
}
int mid = (l + r) >> 1;
if (mr <= mid) {
modify((tId * 2) + 1, l, mid, ml, mr, v);
} else if (ml > mid) {
modify((tId * 2) + 2, mid + 1, r, ml, mr, v);
} else {
modify((tId * 2) + 1, l, mid, ml, mid, v);
modify((tId * 2) + 2, mid + 1, r, mid + 1, mr, v);
}
push(tId);
}
};
int arr[234567];
int main() {
int n, q;
cin >> n >> q;
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
sort(arr, arr + n);
segtree st(arr, n);
while (q--) {
int x;
int l = 0, r = n - 1;
scanf("%d", &x);
while (l <= r) {
int mid = (l + r) >> 1;
if (st.get(0, 0, n - 1, mid) < x) l = mid + 1;
else r = mid - 1;
}
if (l >= n) {
cout << "0" << "\n";
} else {
cout << n - 1 - l + 1 << "\n";
st.modify(0, 0, n - 1, l, n - 1, -1);
}
}
return 0;
} #include <bits/stdc++.h>
using namespace std;
const int N = 200010;
int a[N], hs[N];
int n, q, x;
int main() {
scanf("%d%d", &n, &q);
int x;
for (int i = 1; i <= n; ++ i) {
scanf("%d", &a[i]);
}
sort(a + 1, a + n + 1, greater<int>());
while (q -- ) {
scanf("%d", &x);
int ret = 0;
for (int i = 1; i <= n; ++ i) {
if (a[i] >= x) {
a[i] -= 1;
ret ++ ;
} else {
break;
}
}
printf("%d\n", ret);
}
return 0;
}
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int q = scanner.nextInt();
int[] arr = new int[n];
//将数字录入数组
for (int i = 0; i < n; i++) {
int num = scanner.nextInt();
arr[i] = num;
}
//先将数组排序
Arrays.sort(arr);
//查询次数
for (int i = 0; i < q; i++) {
//需要查询的数字
int x = scanner.nextInt();
System.out.println(demo4(arr, x));
}
}
public static int demo4(int[] arr, int x) {
int count = 0;
//从大往小比较,碰到小于x的及时终止循环,能优化时间
for (int i = arr.length-1; i >= 0; i--) {
if (arr[i] >= x) {
arr[i]--;
count++;
} else {
break;
}
}
return count;
}
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
class SegmentTree {
vector<int> data;
struct TreeNode {
int sum;
int add;
};
vector<TreeNode> tree;
public:
template <typename T>
SegmentTree(T&& data) : data(forward<T>(data)) {
int n = this->data.size();
tree.resize(n * 4);
build(0, 0, n - 1);
}
private:
// [l,r]表示idx掌管的区间
void build(int idx, int l, int r) {
if (l == r) {
tree[idx].sum = data[l];
tree[idx].add = 0;
} else {
int mid = getMiddle(l, r);
// 递归左右区间
build(childLeft(idx), l, mid);
build(childRight(idx), mid + 1, r);
// 左右区间都建立好了,更新idx即可
update(idx);
}
}
/*
idx表示当前树节点的索引
l,r表示idx掌管的区间
s,t表示要获取[l,r]区间在[s,t]范围内的和
*/
int query(int idx, int l, int r, int s, int t) {
if (s <= l && r <= t) {
// 直接返回即可
return tree[idx].sum;
}
pushdown(idx, l, r);
int mid = getMiddle(l, r), ans = 0;
if (mid >= s) ans += query(childLeft(idx), l, mid, s, t);
if (mid < t) ans += query(childRight(idx), mid + 1, r, s, t);
return ans;
}
/*
idx表示当前树节点的索引
l,r表示idx掌管的区间
s,t表示要在[s,t]上都加上一个数
*/
void add(int idx, int l, int r, int s, int t, int val) {
if (s <= l && r <= t) {
// 直接加上即可
tree[idx].add += val;
tree[idx].sum += val * (r - l + 1);
return;
}
pushdown(idx, l, r);
int mid = getMiddle(l, r);
if (mid >= s) add(childLeft(idx), l, mid, s, t, val);
if (mid < t) add(childRight(idx), mid + 1, r, s, t, val);
update(idx);
}
// 使得tree[idx].sum是正确的
void update(int idx) {
tree[idx].sum = tree[childLeft(idx)].sum + tree[childRight(idx)].sum;
}
// 将tree[idx].add传递给左右节点,确保左右节点的add是正确的
void pushdown(int idx, int l, int r) {
auto& root = tree[idx];
int mid = getMiddle(l, r);
int lc = childLeft(idx);
int rc = childRight(idx);
auto &lr = tree[lc], &rr = tree[rc];
lr.sum += root.add * (mid - l + 1);
lr.add += root.add;
rr.sum += root.add * (r - mid);
rr.add += root.add;
root.add = 0;
}
// 获取左子节点
static int childLeft(int index) { return index * 2 + 1; }
// 获取右子节点
static int childRight(int index) { return index * 2 + 2; }
// 平分[l,r]为[l,mid] , [mid+1,r] , 返回mid
static int getMiddle(int l, int r) { return l + (r - l) / 2; }
public:
int get(int idx) { return query(0, 0, data.size() - 1, idx, idx); }
// 在[l,r]区间加上某个值
void add(int l, int r, int val) { add(0, 0, data.size() - 1, l, r, val); }
};
int main() {
int n, q, x;
cin >> n >> q;
vector<int> a(n);
for (auto& v : a) cin >> v;
sort(a.begin(), a.end());
SegmentTree tree(move(a));
// 线段树+二分
while (q--) {
cin >> x;
auto deal = [&]() {
if (tree.get(n - 1) < x) return 0;
// 查询>=x的最小下标
// 二分查找满足条件的最小值,lr左闭右开
int l = 0, r = n;
while (l + 1 < r) {
int mid = l + ((r - l) >> 1);
tree.get(mid) >= x ? r = mid : l = mid;
}
if (r == 1 && tree.get(0) >= x) --r;
tree.add(r, n - 1, -1);
// cout << "find : " << r << endl;
return n - r;
};
cout << deal() << endl;
// cout << "seq : ";
// for (int i = 0; i < n; ++i) cout << tree.get(i) << ' ';
// cout << endl;
}
return 0;
} 随机生成几组数试了一下 import random import numpy as np n=random.randint(1,20) x=np.random.randint(1,10,random.randint(1,10)) s=np.random.randint(1,20,n) for i in x: print(len(s[s>=i])) s=np.where(s>=i,s-1,s)
n,q=map(int,input().split()) arr=list(map(int,input().split())) arr.sort() flag=0 for i in range(q): x=int(input()) if x in arr: t=arr.index(x) arr[t:n]=[m-1 for m in arr[t:n]] print(n-t) else: for j in range(n): if arr[j]>=x: arr[j:n]=[m-1 for m in arr[j:n]] flag=1 print(n-j) break if flag==0: print(0)
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n,q,pos,x;
cin>>n>>q;
int*a=new int[n];
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
while(q-->0){
cin>>x;
pos=lower_bound(a,a+n,x)-a;
cout<<n-pos<<endl;
for(;pos<n;pos++) a[pos]--;
}
return 0;
} nq = input().split(" ")
n = int(nq[0])
q = int(nq[1])
def juge(x,datalist):
rst = 0
for i in range(len(datalist)):
if datalist[i] >= x:
rst += 1
datalist[i] = datalist[i]-1
return rst,datalist
result = []
sn = list(map(int,input().split(" ")))
for i in range(q):
x = int(input().split(" ")[0])
rst,sn = juge(x,sn)
result.append(rst)
for j in result:
print(j)
求解答,我哪里出问题了?感觉在自己的IDE能正常运行呀
import java.util.Arrays;
import java.util.Scanner;
public class Main{
static int search(int[] array,int value) {
int left=0;
int right=array.length-1;
int mid=0;
while(left<=right) {
mid=(left+right)>>1;
if(value<=array[mid])
right=mid-1;
else
left=mid+1;
}
return left<array.length?left:array.length;
}
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int q=scanner.nextInt();
int[] a=new int[n];
for(int i=0;i<n;i++)
a[i]=scanner.nextInt();
Arrays.sort(a);
for(int i=0;i<q;i++) {
int x=scanner.nextInt();
int ind=search(a, x);
System.out.println(n-ind);
for(int j=ind;j<n;j++)
a[j]--;
}
}
} while(line1 = readline()){
let line1Arr = line1.split(' ');
let n = parseInt(line1Arr[0]);
let q = parseInt(line1Arr[1]);
let arr = readline().split(' ').map((it)=>parseInt(it));
for(let i=0;i<q;i++){
let x = parseInt(readline());
let count = 0;
arr.forEach((val,index)=>{
if(val >= x){
count++;
arr[index] = --val;
}
})
print(count);
}
}
用js总是通不过是为什么啊,我实在是看不出有什么问题??
n,q = list(map(int, input().split(' ')))
if n != '':
nums = sorted(list(map(int, input().split(' '))),reverse=True)
for _ in range(q):
x = int(input())
res = 0
for i in range(n):
if nums[i] >= x:
nums[i] -= 1
res += 1
else:
break
print(res)