他们摆出了一座高高的香槟塔,牛牛负责听妞妞指挥,往香槟塔里倒香槟。
香槟塔有个很优雅的视觉效果就是如果这一层的香槟满了,就会从边缘处往下一层流去。
妞妞会发出两种指令,指令一是往第x层塔内倒体积为v的香槟,指令二是询问第k层塔香槟的体积为多少。
告诉你香槟塔每层香槟塔的初始容量,你能帮牛牛快速回答妞妞的询问吗?
第一行为两个整数n,m。表示香槟塔的总层数和指令条数。
第二行为n个整数ai,表示每层香槟塔的初始容量。第三行到第2+m行有两种输入,一种输入是“2 x v”表示往第x层倒入体积为v的香槟;另一种输入是“1 k”表示询问第k层当前有多少香槟。1 <= n, m <= 1000。
1 <= n ,m <= 200000,1 <= ai ,v <= 1000000000。
对于每个询问,输出一个整数,表示第k层香槟的容量。
1 2 8 2 1 9 1 1
8
5 4 1 2 2 10 1 1 3 2 2 5 2 4 3 1 4
0 4
/*思路:线段树维护区间剩余容量和,查询操作直接输出,
从x层倒入操作则二分查找倒入的液体能到达的层数r,此时x到r-1层剩余容量为0,故区间更新为0,
单点更新r层剩余容量 = x到r层总容量tmp - 导入液体总体积val
(时间长没写线段树,忘了懒惰标记怎么用了,参考下楼里某位dalao的标记。很好用哈哈
*/
#include <bits/stdc++.h>
#define lc rt << 1
#define rc rt << 1 | 1
#define LL long long
using namespace std;
const int AX = 2e5 + 666 ;
LL s[AX<<2] ; // 维护各层剩余容量和
int lazy[AX<<2];
LL v[AX] ;
int n , m ;
LL left_v , tmp ;
void pushUp( int rt ){
s[rt] = s[lc] + s[rc];
return ;
}
void pushDown( int rt ){
if( lazy[rt] != -1 ){
s[lc] = s[rc] = 0 ;
lazy[lc] = lazy[rc] = 1 ;
lazy[rt] = -1 ;
}
return ;
}
void build( int rt , int l , int r ){
if( l == r ){
scanf("%lld",&s[rt]);
v[l] = s[rt] ;
return ;
}
int mid = ( l + r ) >> 1 ;
build( lc , l , mid );
build( rc , mid + 1 , r );
pushUp(rt);
}
void update( int rt , int l , int r , int L , int R , int op ){
if( L > r || R < l ) return ;
if( L <= l && R >= r ){
if( op ){
s[rt] = 0 ;
lazy[rt] = 1 ;
}else s[rt] = left_v ;
return ;
}
int mid = ( l + r ) >> 1 ;
pushDown( rt ) ;
if( l <= mid ) update( lc , l , mid , L , R , op );
if( R > mid ) update( rc , mid + 1 , r , L , R , op );
pushUp(rt) ;
}
LL query( int rt , int l , int r , int L , int R ){
if( L <= l && R >= r ) return s[rt] ;
int mid = ( l + r ) >> 1 ;
LL ans = 0 ;
pushDown( rt );
if( L <= mid ) ans += query( lc , l , mid , L , R ) ;
if( R > mid ) ans += query( rc , mid + 1 , r , L , R );
return ans ;
}
int getR( int l , int r , int x , int val ){ // 查找从x层倒,能满(四声)到哪一层为止
while( l <= r ){
int mid = ( l + r ) >> 1 ;
if( query( 1 , 1 , n , x , mid ) >= val ) r = mid - 1;
else l = mid + 1 ;
}
tmp = query( 1 , 1 , n , x , l ); //查询被倒入液体触及的所有层总容量
return l ;
}
int main(){
memset( lazy , -1 , sizeof(lazy) );
cin >> n >> m ;
build( 1 , 1 , n ) ;
int op , x ;
LL val ;
while( m-- ){
scanf("%d",&op);
if( op == 1 ){
scanf("%d",&x);
printf("%lld\n",v[x] - query( 1 , 1 , n , x , x ) );
}else{
scanf("%d%lld",&x,&val);
int r = getR( x , n , x , val ) ;
left_v = tmp - val ;
if( left_v <= 0 ){ //正好倒满或倒满地上了
update( 1 , 1 , n , x , r , 1 );
}else{
if( r == 1 ) update( 1 , 1 , n , 1 , 1 , 0 ); //第一层都倒不满
else{ //x到r-1层被倒满,剩余体积设为0,r层剩余left_v体积 = tmp(x到r层总容量)-val(总共倒入体积)
update( 1 , 1 , n , x , r - 1 , 1 ) ;
update( 1 , 1 , n , r , r , 0 );
}
}
}
}
return 0 ;
}
Python Solution
假设第 层初始状态值为
,则装满的情况为该层状态值达到
。
假如第1层容积为2,则初始状态值为-2,倒入体积3的酒,则状态值归0,剩余体积1的酒向下流动。
n, m = [int(i) for i in input().split()]
a = [int(i) for i in input().split()]
st = [-i for i in a]
all_ml = [[int(i) for i in input().split()] for i in range(m)]
def pour(st, ml):
'''香槟塔的第x层到体积v的酒'''
x = ml[1]-1
v = ml[2]
while True:
v = v + st[x]
if v < 0:
st[x] = v
break
else:
st[x] = 0
x += 1
if x == len(st):
break
return st
def ask(a, st, ml):
'''k层装酒量=k层容积+k层状态值'''
k = ml[1]
print(a[k-1]+st[k-1])
for ml in all_ml:
if ml[0] == 2:
st = pour(st, ml)
else:
ask(a, st, ml)
/*
判断,循环。哭了,同样的程序python死活超时
*/
#include <bits/stdc++.h>
using namespace std;
#define N 200001
int a[N], b[N];
int main(void)
{
//freopen("input.txt", "r", stdin);
int n, m, op, x, v, k;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
while(m--) {
scanf("%d", &op);
if(op == 1) {
scanf("%d", &k);
printf("%d\n", b[k]);
} else {
scanf("%d%d", &x, &v);
while(x <= n && v > 0) {
if(a[x] - b[x] < v) {
v -= a[x] - b[x];
b[x] = a[x];
x++;
} else {
b[x] += v;
v = 0;
}
}
}
}
return 0;
} n, m = map(int, input().strip().split()) a = list(map(int, input().strip().split())) # 初始情况下每一层被占用的容积为0 occupy = [0]*n for _ in range(m): temp = list(map(int, input().strip().split())) if len(temp) == 3: op, x, v = temp else: op, x = temp if op == 2: # 倒香槟操作 idx = x - 1 # 初始层号 while v and idx < n: if v + occupy[idx] > a[idx]: # 如果要倒的香槟和这一层已经被倒的体积超过了这一层的容积,就要向下流 v -= a[idx] - occupy[idx] # 向下流的体积 occupy[idx] = a[idx] # 更新本层被占用的容积 idx += 1 # 向下更新层号 if idx == n: break else: # 更新本层被占用的容积 occupy[idx] = v + occupy[idx] # 否则没有向下层流的体积 v = 0 else: # 询问操作 print(occupy[x - 1])
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <string.h>
#include <limits.h>
#include <string>
#include <iostream>
#include <queue>
#include <math.h>
#include <map>
#include <stack>
#include <set>
#include <list>
#include <forward_list>
#define left (now<<1)
#define right ((now<<1)+1)
#define mid ((l + r) >> 1)
#define midmid ((r + mid) >> 1)
#define LONG_LONG_MIN -9223372036854775808ll
#define LONG_LONG_MAX 9223372036854775807ll
using namespace std;
typedef long long int ll;
const int MAXN = 2e5 + 10;
const int MOD = 1e9 + 7;
int n,m,nxt[MAXN],pre[MAXN];
ll now[MAXN],a[MAXN];
void init(){
for(int i = 1; i <= n + 1; ++i){
now[i] = 0; nxt[i] = i + 1; pre[i] = i - 1;
}
}
int main(){
scanf("%d%d",&n,&m); init();
for(int i = 1; i <= n; ++i){
scanf("%lld",&a[i]);
}
a[n + 1] = LONG_LONG_MAX / 2ll;
for(int i = 1; i <= m; ++i){
int command; scanf("%d",&command);
if(command == 2){
int x; ll v; scanf("%d%lld",&x,&v);
while(v > 0){
ll p = a[x] - now[x];
if(p >= v){
now[x] += v; v = 0;
}else{
now[x] = a[x]; v -= p;
nxt[pre[x]] = nxt[x];
pre[nxt[x]] = pre[x];
x = nxt[x];
}
}
}else{
int x; scanf("%d",&x);
printf("%lld\n",now[x]);
}
}
return 0;
} #include <bits/stdc++.h>
using namespace std;
int main(){
int n,m,c,x,y;
cin>>n>>m;
int a[n+1],b[n+1];
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=0;i<m;i++){
cin>>c;
if(c==1){
cin>>x;
cout<<b[x]<<endl;
}else{
cin>>x>>y;
int t = a[x]-b[x];
while(y>t && x<=n){
b[x] += t;
if(x<=n){
y -= t;
x++;
t = a[x] - b[x];
}else
break;
}
if(x<=n)
b[x] += y;
}
}
return 0;
} #include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m,q,x,v,k;
cin>>n>>m;
int a[n],b[n];
for(int i=0;i<n;i++)
{
cin>>a[i];
b[i]=0;
}
while(m--)
{
cin>>q;
if(q==1)
{
cin>>k;
cout<<b[k-1]<<endl;
}
if(q==2)
{
cin>>x>>v;
x--;
while(x<n&&v>0)
{
if ((a[x]-b[x])<v)
{
v -= a[x] - b[x];
b[x] = a[x];
x++;
}
else
{
b[x] += v;
v = 0;
}
}
}
}
return 0;
}
#include <bits/stdc++.h>
#define ls o*2
#define rs o*2+1
using namespace std;
const int N = 2e5+7;
int x,y,v,n;
long long O[N<<2],vol[N];
bool laz[N<<2];
void build(int o,int l,int r){
if(l==r){
scanf("%lld",&vol[l]);
O[o] = vol[l];
}else{
int mid = l+(r-l)/2;
build(ls,l,mid);
build(rs,mid+1,r);
O[o] = O[ls]+O[rs];
}
}
void pushdown(int o){
if(laz[o]){
O[ls] = O[rs] = 0;
laz[ls] = laz[rs] = 1;
laz[o] = 0;
}
}
void update(int o,int l,int r,int op){
if(x>r||y<l)return;
if(x<=l&&y>=r){
if(op==1){
laz[o] = 1;
O[o] = 0;
}
else O[o] = v;
}else{
int mid = l+(r-l)/2;
pushdown(o);
if(x<=mid)update(ls,l,mid,op);
if(y>mid)update(rs,mid+1,r,op);
O[o] = O[ls]+O[rs];
}
}
long long query(int o,int l,int r,int L,int R){
if(L<=l&&R>=r)return O[o];
else{
int mid = l+(r-l)/2;
long long ans = 0;
pushdown(o);
if(L<=mid)ans += query(ls,l,mid,L,R);
if(R>mid)ans += query(rs,mid+1,r,L,R);
return ans;
}
}
int find_pos(int l,int r,long long &res){
int mid;
while(l<r){
mid = l+(r-l)/2;
if(query(1,1,n,x,mid)<v)l = mid+1;
else r = mid;
}
res = query(1,1,n,x,l);
return l;
}
int main(){
int m;
scanf("%d %d",&n,&m);
build(1,1,n);
while(m--){
int op;
scanf("%d",&op);
if(op==1){
scanf("%d",&x);
printf("%lld\n",vol[x]-query(1,1,n,x,x));
}else{
long long res = 0;
scanf("%d %d",&x,&v);
y = find_pos(x,n,res);
v = res - v;
if(res!=0){
if(y==n)update(1,1,n,1);
else{
if(y==1){
x = y;
update(1,1,n,0);
}
else{
y--;update(1,1,n,1);
y++;x = y;
update(1,1,n,0);
}
}
}
else update(1,1,n,1);
}
}
return 0;
}
注意:不能用for循环,for循环的时间复杂度太大,要用while
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc=new Scanner(System.in);
int ceng=sc.nextInt();
int zhiling=sc.nextInt();
int[] churong=new int[ceng];
int[] xiangrong=new int[ceng];
int j=0;
while(j<ceng){
int A1=sc.nextInt();
churong[j]=A1;
xiangrong[j]=0;
j++;
}
int z=0;
while(z<zhiling){
int gu=sc.nextInt();
if(gu==1){
int k=sc.nextInt();
int l=xiangrong[k-1];
System.out.println(l);
}else{
int b=sc.nextInt();
int x=b-1;
int v=sc.nextInt();
while(v>0&&x<ceng){
//如果 杯子已有的水<杯子 并且v<杯子-水
if(xiangrong[x]<churong[x]&&v<churong[x]-xiangrong[x]){
xiangrong[x]=xiangrong[x]+v;
v=0;
}
else {
//v=v-(杯子-水)
v=v-(churong[x]-xiangrong[x]);
xiangrong[x]=churong[x];
x++;
}
}
}
z++;
}
}
}
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
unordered_map<int,int> next_layer;
int dfs(int layer,int v,vector<int>& cur,vector<int>& volume){
if(layer==volume.size()) return layer;
int tmp=volume[layer]-cur[layer];
if(tmp>=v){
cur[layer]+=v;
return layer;
}
cur[layer]=volume[layer];
next_layer[layer]=dfs(next_layer[layer],v-tmp,cur,volume);
return next_layer[layer];
}
int main(){
int n,m;
cin>>n>>m;
vector<int> volume(n+1);
vector<int> cur(n+1,0);
for(int i=1;i<=n;++i) cin>>volume[i];
for(int i=1;i<=n;++i) next_layer[i]=i+1;
while(m--){
int op;
cin>>op;
if(op==1){
int layer;
cin>>layer;
cout<<cur[layer]<<endl;
}
else{
int layer,v;
cin>>layer>>v;
if(volume[layer]-cur[layer]>=v) cur[layer]+=v;
else{
next_layer[layer]=dfs(layer,v,cur,volume);
}
}
}
return 0;
} import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
int m = sc.nextInt();
int[][] arr = new int[n][2];
for(int i=0;i<n;i++){
arr[i][0] = sc.nextInt();
}
for(int i=0;i<m;i++){
int o = sc.nextInt();
if(o==1){
int x = sc.nextInt()-1;
System.out.println(arr[x][1]);
}else{
int x = sc.nextInt()-1;
int v = sc.nextInt();
while(v>0 && x<n){
if(v <= arr[x][0]){
arr[x][1] += v;
arr[x][0] -= v;
v = 0;
//x++;
}else{
v -= arr[x][0];
arr[x][1] += arr[x][0];
arr[x][0] = 0;
x++;
}
}
}
}
}
}
} // 38行代码结束战斗,C++
#include <iostream>
#include <vector>
using namespace std;
int main(){
//输入数据
int numLayer, numCmd;
cin >> numLayer >> numCmd;
vector<int> volume(numLayer, 0), used(numLayer, 0);
for (int i=0;i<numLayer;++i)
cin >> volume[i];
while (numCmd--){
int cmd;
cin >> cmd;
//如果是查询
if (cmd == 1){
int where;
cin >> where;
cout << used[where-1] << endl;
}
//如果是灌水
else if (cmd == 2){
int where, amount;
cin >> where >> amount;
while (amount > 0){
//1.边界判断:全都满了
if (where > numLayer) break;
//2.如果不够装满当前层
if (amount <= volume[where-1] - used[where-1]){
used[where-1] += amount;
amount = 0;
}
//3.如果当前层满了,但是还有剩余
else{
amount -= volume[where-1] - used[where-1];
used[where-1] = volume[where-1];
++where;
}
}
}
}
return 0;
}
比较简单,跟着题目意思走就行
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* @Author: coderjjp
* @Date: 2020-05-08 17:47
* @Description:
* @version: 1.0
*/
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line1[] = br.readLine().split(" ");
int n = Integer.valueOf(line1[0]);//层数
int m = Integer.valueOf(line1[1]);//总指令数
int V[] = new int[n+1];
String[] line2 = br.readLine().split(" ");
for (int i = 0; i < n; i++)
V[i+1] = Integer.valueOf(line2[i]);
int cur[] = new int[n+1];//初始体积
while (m-- > 0){
String linex[] = br.readLine().split(" ");
int order[] = new int[linex.length];
for (int i = 0; i < linex.length; i++)
order[i] = Integer.valueOf(linex[i]);
if (order[0] == 1)
System.out.println(cur[order[1]]);
else{
int rem = order[2];
for (int i = order[1]; i <= n && rem > 0; i++){
if (cur[i] == V[i])
continue;
if (rem >= V[i]-cur[i]){
rem = rem - (V[i] - cur[i]);
cur[i] = V[i];
}else {
cur[i] += rem;
rem = 0;
}
}
}
}
}
} import copy n,m = map(int,input().split()) nums = list(map(int,input().split())) nums = [0]+nums flag = copy.deepcopy(nums) for _ in range(m): op = list(map(int,input().split())) if len(op)==3: k,v= op[1],op[2] index = k while v>0 and index<n: if v>flag[index]: v = v- flag[index] flag[index] = 0 index+=1 else: flag[index] = flag[index]-v v = 0 else: k = op[1] print(nums[k] - flag[k])
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();//香槟塔总层数
int m = sc.nextInt();//指令条数
long[] a = new long[n];// 初始容量
for (int i = 0; i < n; i++) {
a[i] = sc.nextLong();
}
long[] champagnes = new long[n];//塔的 Champagne 量
for (int i = 0; i < m; i++) {
int flag = sc.nextInt();
if (flag == 1) {
int k = sc.nextInt() - 1;//询问第 k 层
System.out.println(champagnes[k]);
} else {
int x = sc.nextInt() - 1;//往第 x 层倒 Champagne
long v = sc.nextLong();//倒入的 Champagne 体积
pourChampagne(x, v, a, champagnes);
}
}
}
private static void pourChampagne(int towerIndex, long volume, long[] a, long[] champagnes) {
if (towerIndex >= a.length) {
return;
}
long capacity = a[towerIndex];//当前层的容量
long champagne = champagnes[towerIndex];//当前层的 Champagne 量
if (champagne == capacity) {
pourChampagne(towerIndex + 1, volume, a, champagnes);
return;
}
if (champagne + volume <= capacity) {
champagnes[towerIndex] += volume;
} else {
long residual = volume - (capacity - champagne);//当前层填满后流入下一层的余量
champagnes[towerIndex] = capacity;
pourChampagne(towerIndex + 1, residual, a, champagnes);
}
}
} c,z=list(map(int,input().split(" "))) r1=list(map(int,input().split(" "))) r2=[0 for i in range(c)] re=[] while z>0: in1=list(map(int,input().split(" "))) if in1[0]==1: re+=[r2[in1[1]-1]] elif in1[0]==2: while in1[1]<=c : k=in1[1]-1 if r1[k]==r2[k]: in1[1]+=1 continue if r1[k]>r2[k]: r2[k]=r2[k]+in1[2] if r2[k]>=r1[k]: in1[2]=r2[k]-r1[k] r2[k]=r1[k] in1[1]+=1 else:break z-=1 for i in re: print(i)
n, m = map(int, input().split()) a = [int(i) for i in input().split()] b = [0 for i in range(n)] for i in range(m): order = [int(j) for j in input().split()] if order[0] == 1: print(b[order[1]-1]) else: k = 0 while b[order[1]+k-1]+order[2] > a[order[1]+k-1] and order[1]+k < n: order[2] = order[2] - (a[order[1]+k-1]-b[order[1]+k-1]) b[order[1]+k-1] = a[order[1]+k-1] k += 1 b[order[1] + k-1] += min(order[2], (a[order[1]+k-1]-b[order[1] + k-1]))
#include <iostream>
#include <vector>
using namespace std;
int main(void){
int n, m, oper, i, v, tmp_vol;
cin>>n>>m;
vector<int> volume(n, 0), contain(n, 0);
for(int i = 0; i < n; ++i)
cin>>volume[i];
while(m--){
cin>>oper>>i;
--i;
if(oper == 1)
cout<<contain[i]<<endl;
else{
cin>>v;
while(v + contain[i] >= volume[i] && i < n){
v = v + contain[i] - volume[i];
contain[i] = volume[i];
//写在上一句语句前面
//v = v + contain[i] - volume[i];
++i;
}
//用+=而不是=
if(i < n)
contain[i] += v;
}
}
return 0;
}