D - Sequence Query
题意:
三种操作:
1 x :将 x 插入集合中;
2 x k :找到集合中 ≤ x 的第 k 个最大的值;
3 x k :找到集合中 ≥ x 的第 k 个最小的值。
思路:
multiset 操作,每次插入复杂度为 logN。
操作2,upper_bound(x) 找到第一个 >x 的值的迭代器,将迭代器往左移 k 位;
操作3,lower_bound(x) 找到第一个 ≥x 的值的迭代器,将迭代器往右移 k-1 位。
注意看是不是到 最左端:begin()
或者 最右端:end()-1
了。
Code:
const int N = 200010, mod = 1e9+7;
int T, n, m, k;
int a[N];
multiset<int> st;
signed main(){
Ios;
cin>>m;
while(m--)
{
int t;cin>>t;
if(t==1){
int x;cin>>x;
st.insert(x);
}
else if(t==2)
{
int x;cin>>x>>k;
auto it = st.upper_bound(x);
int flag=0;
for(int i=1;i<=k;i++)
{
if(it == st.begin()){flag=1;break;}
it--;
}
if(flag) cout << -1 <<endl;
else cout << *it <<endl;
}
else
{
int x;cin>>x>>k;
auto it = st.lower_bound(x);
int flag=0;
if(it==st.end()) flag=1;
else
for(int i=1;i<k;i++)
{
it++;
if(it == st.end()){flag=1;break;}
}
if(flag) cout << -1 <<endl;
else cout << *it << endl;
}
}
return 0;
}
经验:
E - Putting Candies
思路:
大模拟,找循环节。(但是写了好长时间。。
Code:
map<int,int> mp;
const int N = 200010, mod = 1e9+7;
int T, n, m, k;
int a[N], b[N];
signed main(){
Ios;
cin>>n>>m;
for(int i=0;i<n;i++) cin>>a[i];
int x=0, st, len;
for(int i=1;;i++)
{
if(mp[x%n])
{
st = mp[x%n]; //循环节起点位置
len = i-mp[x%n]; //长度
break;
}
else mp[x%n] = i;
b[i] = x%n;
x += a[x%n];
}
if(m<st)
{
x=0;
for(int i=1;i<=m;i++)
x += a[x%n];
cout << x;
return 0;
}
m-=st;
int times = m/len; //循环节个数
m %= len; //剩余位置个数
x = 0;
for(int i=1;i<st;i++) x += a[x%n]; //循环节前面位置和
int y=0;
for(int i=st;i<st+len;i++) y+=a[b[i]]; //循环节位置和
for(int i=st;i<=st+m;i++) //最后长度不够循环节的位置和
{
x += a[b[i]];
}
cout << x+times*y;
return 0;
}