NOIP2017金秋冲刺训练营杯联赛模拟大奖赛Day1

前言:昨天晚上没睡好,导致今天早上起来头疼,于是睡了一多个小时,本来不想比赛了,但是发现第一题的做法实在是太显而易见,于是就愉快的AC了

T1

很简单的一道线段树问题

天天去哪吃

题目大意

小天在第i天去了第x[i]号餐厅吃饭,并且在接下来的n/2天内都不能再去这个餐厅去吃饭了,$x[i]=(a*x[i-1]+b*x[i-2]+k)\%n$  (k是能使x[i]合法的最小值,即x[i]在x[i-n/2~i-1]中没有出现过)

输入

n,m,a,b,x[1],x[2]

输出

x[3],x[4]……x[m]

 

注意到数据之间的关联(大小关系,这个技巧简直太好用了),还有我们需要求解的问题(快速查找$(a*x[i-1]+b*x[i-2]+k)\%n$在剩余系下在它右边距离最近的合法值),而且还要支持单点修改(把x[i-n/2-1]加入,再把x[i]删除),很明显这是一颗线段树……所以$O(mlogn)$

但是有个问题,如果$(a*x[i-1]+b*x[i-2]+k)\%n$到$n$之间的所有数都被删完了怎么办,由于剩余系的原因我们还需要从1开始向右接着找……好像有点麻烦是不是?

当然其实我们还有更好的方法,因为剩余系可以抽象成一个环,所以我们可以把这个环破开变成长度为2*n的线段,每次修改x[i]的时候只要同时修改x[i]+n即可

但是还有个问题(问题怎么这么多QWQ),如果查找的过程在线段上跨越了超过n的长度怎么办?其实不用担心,因为剩余系里最多只能同时删掉n/2个数,所以最多只需要跨越n/2的长度就会找到我们需要的数了

后记:果然是自己想太多了……随机数据直接模拟就能拿100分

 1 #include <cstdio>
 2 #include <iostream>
 3 using namespace std;
 4 struct T{
 5     int l,r,f,w;
 6 }t[200001*4];
 7 int n,n_2,m,q,f[200001];
 8 long long a,b;
 9 int build(int x,int l,int r)
10 {
11     t[x].l=l,t[x].r=r,t[x].w=r-l+1;
12     if (l==r) return t[x].w;
13     int mid=(l+r)/2;
14     build(x*2,l,mid);build(x*2+1,mid+1,r);
15 }
16 int query(int x,int l)
17 {
18     if (t[x].w==0||t[x].r<l) return -1;
19     if (t[x].l==t[x].r) return t[x].l;
20     int ret=query(x*2,l);
21     if (ret>=0) return ret;
22     return query(x*2+1,l);
23 }
24 void update(int x,int l,int upd)
25 {
26     if (l<t[x].l||l>t[x].r) return;
27     t[x].w+=upd;
28     if (t[x].l==t[x].r) return;
29     update(x*2,l,upd);update(x*2+1,l,upd);
30 }
31 int main()
32 {
33     freopen("lunch.in","r",stdin);
34     freopen("lunch.out","w",stdout);
35     ios::sync_with_stdio(false);
36     cin>>n>>m>>a>>b>>f[1]>>f[2];
37     build(1,0,2*n-1);
38     update(1,f[1],-1);update(1,f[1]+n,-1);
39     update(1,f[2],-1);update(1,f[2]+n,-1);
40     n_2=n/2;
41     for (int i=3;i<=m;i++)
42     {
43         if (i-n_2-1>=1){update(1,f[i-n_2-1],1);update(1,f[i-n_2-1]+n,1);}
44         f[i]=query(1,int((a*f[i-1]+b*f[i-2])%n))%n;
45         update(1,f[i],-1);update(1,f[i]+n,-1);
46         cout<<f[i]<<" ";
47     }
48 }

 

T2

二分答案k,一眼就看出来,可是没时间写了

fyz的另一种思路:直接找最长路即可(类似有机物命名)

转载于:https://www.cnblogs.com/algonote/p/7532447.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值