《P7167 [eJOI 2020] Fountain (Day1)》
题目描述
大家都知道喷泉吧?现在有一个喷泉由 N 个圆盘组成,从上到下以此编号为 1∼N,第 i 个喷泉的直径为 Di,容量为 Ci,当一个圆盘里的水大于了这个圆盘的容量,那么水就会溢出往下流,直到流入半径大于这个圆盘的圆盘里。如果下面没有满足要求的圆盘,水就会流到喷泉下的水池里。
现在给定 Q 组询问,每一组询问这么描述:
- 向第 Ri 个圆盘里倒入 Vi 的水,求水最后会流到哪一个圆盘停止。
如果最终流入了水池里,那么输出 0。
注意,每个询问互不影响。
输入格式
第一行两个整数 N,Q 代表圆盘数和询问数。
接下来 N 行每行两个整数 Di,Ci 代表一个圆盘。
接下来 Q 行每行两个整数 Ri,Vi 代表一个询问。
输出格式
Q 行每行一个整数代表询问的答案。
输入输出样例
输入 #1复制
6 5 4 10 6 8 3 5 4 14 10 9 4 20 1 25 6 30 5 8 3 13 2 8
输出 #1复制
5 0 5 4 2
说明/提示
样例 1 解释
前两个询问的解释如下图所示:
因为每个询问互不影响,对于第三个询问,第 5 个圆盘里的水不会溢出。
数据规模与约定
本题采用捆绑测试。
- Subtask 1(30 pts):N≤1000,Q≤2000。
- Subtask 2(30 pts):Di 为严格单调递增序列。
- Subtask 3(40 pts):无特殊限制。
对于 100% 的数据:
- 2≤N≤105。
- 1≤Q≤2×105。
- 1≤Ci≤1000。
- 1≤Di,Vi≤109。
- 1≤Ri≤N。
说明
翻译自 eJOI 2020 Day1 A Fountain。
代码实现1:
#include <iostream>
#include <vector>
using namespace std;
vector<int> a;
vector<int> b;
vector<int> c;
vector<int> d;
int search(vector<int> a,vector<int> b,vector<int> c,int k1,int k2,int n )
{ int sum=0;
int flag=0;
int r=0;
int k=0;
for(int i=0;i<n;i++)
{
if(c[i]==k1)
{
k2-=b[i];
r=a[i];
flag=1;
}
if(flag==1 && a[i]>r)
{
k2-=b[i];
r=a[i];
}
if(k2<=0)
{
k=c[i];
break;
}
//cout<<sum<<endl;
}
return k;
}
int main() {
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
{
int x,y;
cin>>x>>y;
a.push_back(x);
b.push_back(y);
c.push_back(i+1);
}
while(m)
{ int k1,k2;
cin>>k1>>k2;
int mm=search(a,b,c,k1,k2,n);
d.push_back(mm);
m--;
}
for (int i = 0; i < d.size(); ++i) {
cout << d[i] << endl; // 使用d[i]访问元素
}
return 0;
}
代码实现·2:
#include<bits/stdc++.h>
using namespace std;
#define re register
#define maxn 100010
#define inf 0x7f7f7f7f
#define int long long
#define Orz cout<<"stO %王队% Orz"<'\n';
int n,q;
struct node
{
int d,c;
}a[maxn];
int s[maxn],size;
int f[maxn][25],u[maxn][25];
inline int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0'; ch=getchar();}
return x*f;
}
signed main()
{
cin>>n>>q;
for(re int i=1;i<=n;++i)
a[i].d=read(),a[i].c=read();//读入数据
for(re int i=n;i>=1;--i)
{
while(size&&a[s[size]].d<=a[i].d) size--;
f[i][0]=s[size];
s[++size]=i;
} //单调栈
for(re int i=1;i<=23;++i)
for(re int j=1;j<=n;++j)
f[j][i]=f[f[j][i-1]][i-1];
for(re int i=1;i<=n;++i)
u[i][0]=a[f[i][0]].c;
for(re int i=1;i<=n;++i)
if(f[i][0]==0)
u[i][0]=inf; //初始化u数组
for(re int i=1;i<=23;++i)
for(re int j=1;j<=n;++j)
u[j][i]=u[j][i-1]+u[f[j][i-1]][i-1];//倍增
while(q--)
{
int r=read(),v=read();
if(v<=a[r].c)
{
cout<<r<<'\n';
continue;
}
v-=a[r].c;
for(re int i=23;i>=0;--i)
if(u[r][i]<=v)
v-=u[r][i],r=f[r][i];
if(v) r=f[r][0];
cout<<r<<'\n';
}//回答询问
return 0;
}