这一题真是累死我了,比赛的时候搞了一个树状数组结果TLE,最后还是队友写了一个线段树才过的,不就是树状数组多了一个logn嘛TAT,还有的大佬要是再卡一个常数,线段树可能都过不了TAT
等到下来补题的时候,单调队列不懂怎么做TAT,就开始搞线段树,我觉得写得很对啊怎么又错了TAT,好吧换一种写法,看到有一种优先队列的写法,正确性自己想了想就写了,然后交上去还是错的TAT,怎么回事啊啊啊啊啊TAT
然后发现我预编译的东西没删掉,所以一直打开的是测试文件TAT
心好痛TAT,我怎么这么菜啊TAT
优先队列版本:
#include <bits/stdc++.h>
using namespace std;
// #define test TEST
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
typedef long long ll;
const int mod=1e9+7;
const int maxn=250005;
int a[maxn<<1],b[maxn],bucket[maxn];
int n;
// int que[maxn],Max[maxn],pos[maxn];
void bucketsort(int vv){
memset(bucket,0,sizeof(bucket));
for(int i=0;i<n;i++){
bucket[b[i]]++;
}
for(int i=0,j=0;i<=vv;i++){
while(bucket[i]){
b[j++]=i;
bucket[i]--;
}
}
}
typedef struct Node{
int id,val;
bool operator < (const Node &x) const {
if(val!=x.val) return val<x.val;
else return id>x.id;
}
}node;
int main(int argc, char const *argv[])
{
#ifdef test
freopen("test.txt","r",stdin);
#endif
while(~scanf("%d",&n)){
node temp;
priority_queue<node>que;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
temp.id=i,temp.val=a[i]-i;
que.push(temp);
}
int vv=0;
for(int i=0;i<n;i++){
scanf("%d",&b[i]);
vv=max(vv,b[i]);
}
bucketsort(vv);//桶排
for(int i=n+1;i<=n+n;i++){
temp=que.top();
while(b[i-n-1]>temp.id){
que.pop();
temp=que.top();
}
a[i]=temp.val;
temp.id=i,temp.val=a[i]-i;
que.push(temp);
}
int ans=0;
for(int i=n+1;i<=n+n;i++){
ans=(ans+a[i])%mod;
}
printf("%d\n",ans);
}
return 0;
}
线段树版本:
#include <bits/stdc++.h>
using namespace std;
//#define test TEST
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
typedef long long ll;
const int mod=1e9+7;
const int maxn=250005;
int a[maxn<<1],b[maxn],bucket[maxn];
int n;
// int que[maxn],Max[maxn],pos[maxn];
void bucketsort(int vv){
memset(bucket,0,sizeof(bucket));
for(int i=0;i<n;i++){
bucket[b[i]]++;
}
for(int i=0,j=0;i<=vv;i++){
while(bucket[i]){
b[j++]=i;
bucket[i]--;
}
}
}
typedef struct Node{
int id,val;
bool operator < (const Node &x) const {
if(val!=x.val) return val<x.val;
else return id>x.id;
}
}node;
int main(int argc, char const *argv[])
{
#ifdef test
freopen("test.txt","r",stdin);
#endif
while(~scanf("%d",&n)){
node temp;
priority_queue<node>que;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
temp.id=i,temp.val=a[i]-i;
que.push(temp);
}
int vv=0;
for(int i=0;i<n;i++){
scanf("%d",&b[i]);
vv=max(vv,b[i]);
}
bucketsort(vv);//桶排
for(int i=n+1;i<=n+n;i++){
temp=que.top();
while(b[i-n-1]>temp.id){
que.pop();
temp=que.top();
}
a[i]=temp.val;
temp.id=i,temp.val=a[i]-i;
que.push(temp);
}
int ans=0;
for(int i=n+1;i<=n+n;i++){
ans=(ans+a[i])%mod;
}
printf("%d\n",ans);
}
return 0;
}
再贴一份别人家的单调队列代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define LL long long
const int mod = 1e9+7;
const int maxn = 250010;
int n;
int a[maxn];
int b[maxn];
struct Node{
int id;
int val;
};
Node q[maxn<<1];
int main()
{
while( ~scanf("%d",&n))
{
int head = 0;
int tail = 0;
for( int i = 1; i <= n; i++)
{
scanf("%d",&a[i]);
if( tail == 0)
{
q[tail].id = i;
q[tail++].val = a[i]-i;
}
else
{
while( head < tail && a[i]-i >= q[tail-1].val)
tail--;
q[tail].id = i;
q[tail++].val = a[i]-i;
}
}
for( int i = 1; i <= n; i++)
scanf("%d",&b[i]);
sort(b+1,b+1+n);
int p = 1;
Node tmp;
LL ans = 0;
while( p <= n)
{
while( b[p] > q[head].id)
head++;
ans = (ans+q[head].val)%mod;
tmp.id = p+n;
tmp.val = q[head].val-(n+p);
while( head < tail && tmp.val >= q[tail-1].val)
tail--;
q[tail++] = tmp;
p++;
}
printf("%lld\n",ans);
}
return 0;
}