计蒜客掷标枪

题目链接:https://www.jisuanke.com/problem/T3778

题目要求你根据公式依次算出每个人的掷标枪的距离然后计算得分,得分=离当前标枪落点最近后落点和前落点的标枪的距离之和

准确来说是这样的:

 

 让我们来计算得分;

这道题用暴力和set+二分都不行,6e6超了,后者的做法是o(nlogn)级别,只能过80%

正确的做法是双向链表维护(不得不说这道题真的给我好好上了一课)

参考代码:

 1 //因为xi = (ai%n) + 1 ≤ n,即1 ≤ xi ≤ 6 × 10^6,可是使⽤桶进⾏计数排序,然后建⽴有序的双向链表,
 2 //注意因为要找大于或小于的值,因此链表内重复的数字只加⼊⼀次。
 3 //题⽬求解的是依次加⼊xi时,计算结果之和,因为链表是通过计数排序建⽴的,
 4 //因此可以转变思路:从最后⼀个数开始逆序删除每个数,计算答案。
 5 //因为要删除,需要快速找到每个数在双向链表中位置,因此在建⽴双向链表的时候让xi位于索引xi处。
 6 //每次删除时,让桶中这个数字的次数减少1,当减少到0时,将该数从双向链表中删除。
 7 //总体的时间复杂度:O(n)
 8 
 9 #include<bits/stdc++.h>
10 using namespace std;
11 #define int long long
12 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);;
13 const int mod=1e9+7;
14 const int N=6e6+10;
15 int x[N],cnt[N];
16 int nxt[N],pre[N];
17 int n,B,A,C;
18 int a;
19 int tot,sum;
20 inline int read(){
21      int s=0,w=1;char ch=getchar();
22     while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
23     while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
24     return s*w;
25 }
26 inline void write(int x)
27 {
28     if (x < 0) putchar('-'), x = -x;
29     if(x > 9)
30         write(x / 10);
31     putchar(x % 10 + '0');
32     return;
33 }
34 signed main()
35 {
36     IOS;
37     freopen("javelin.in", "r", stdin);
38     freopen("javelin.out", "w", stdout);
39     //n=read(),A=read(),B=read(),C=read(),a=read();
40     cin>>n>>A>>B>>C>>a;
41     x[1]=(a%n)+1;
42     cnt[x[1]]++;
43     for(int i=2;i<=n;i++)
44     {
45         a=(A*a%mod*a%mod+B*a%mod+C)%mod;
46         x[i]=(a%n)+1;
47         cnt[x[i]]++;
48     }
49     for(int i=0;i<N;i++)
50     {
51         if(cnt[i])
52         {
53             nxt[tot]=i;
54             pre[i]=tot;
55             tot=i;
56         }
57     }
58     nxt[tot]=N-9;
59     pre[N-9]=tot;;
60     for(int i=n;i>=1;i--)
61     {
62          int id=x[i];
63          if(nxt[id]!=N-9)
64          {
65              sum=(sum+nxt[id])%mod;
66          }
67          if(pre[id]!=0)
68          {
69              sum=(sum+pre[id])%mod;
70          }
71          cnt[id]--;
72          if(cnt[id]==0)
73          {
74              nxt[pre[id]]=nxt[id];
75              pre[nxt[id]]=pre[id];
76          }
77     }
78     cout<<sum<<endl;
79     return 0;
80 }

 

posted @ 2023-01-15 13:37  江上舟摇  阅读(101)  评论(0编辑  收藏  举报