洛谷mNOIP模拟赛Day1-数颜色

传送门

题目大意:

给定一个序列,维护每个数字在[L,R]出现的次数以及交换a[x]和a[x+1]的操作

一开始想的分桶法,感觉复杂度还可以吧,常数有点大,于是死得很惨(65分)

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<map>
  7 #include<set>
  8 #include<queue>
  9 #include<vector>
 10 #define INF 0x7f7f7f7f
 11 #define pii pair<int,int>
 12 #define ll long long
 13 #define SIZE 2505
 14 #define MAXN 300005
 15 using namespace std;
 16
 17 int read(){
 18     int x=0,f=1;char ch=getchar();
 19     while(ch<‘0‘||ch>‘9‘){if(‘-‘==ch)f=-1;ch=getchar();}
 20     while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 21     return x*f;
 22 }
 23 int n,num,len;
 24 struct Bucket{
 25     int L;
 26     int a[SIZE];
 27     vector<int> v;
 28     Bucket(){
 29         L=-1;
 30         memset(a,0,sizeof(a));
 31     }
 32     void add(int x){
 33         a[++L]=x;
 34         vector<int>::iterator P=lower_bound(v.begin(),v.end(),x);
 35         v.insert(P,x);
 36     }
 37 }s[250];
 38 //pos:id->position
 39 //id:
 40 int main()
 41 {
 42 //    freopen("data.in","r",stdin);
 43 //    freopen("my.out","w",stdout);
 44     n=read();int T=read();
 45     len=pow(1.0*n,0.618);
 46     num=(n-1)/len;
 47     for(int i=0;i<n;i++){
 48         s[i/len].add(read());
 49     }
 50     while(T--){
 51         int p=read();
 52         int numl=0,numr=0,posl=0,posr=0;
 53         if(1==p){
 54             int ans=0;
 55             int l=read(),r=read(),c=read();
 56             l--,r--;
 57             numl=l/len,numr=r/len;
 58             posl=l%len,posr=r%len;
 59             if(numl!=numr){
 60                 for(int i=numl+1;i<numr;i++){
 61                     ans+=upper_bound(s[i].v.begin(),s[i].v.end(),c)-lower_bound(s[i].v.begin(),s[i].v.end(),c);
 62                 }
 63                 for(int i=posl;i<=s[numl].L;i++){
 64                     if(s[numl].a[i]==c){
 65                         ans++;
 66                     }
 67                 }
 68                 for(int i=0;i<=posr;i++){
 69                     if(s[numr].a[i]==c){
 70                         ans++;
 71                     }
 72                 }
 73             }
 74             else{
 75                 for(int i=posl;i<=posr;i++){
 76                     if(s[numl].a[i]==c){
 77                         ans++;
 78                     }
 79                 }
 80             }
 81             printf("%d\n",ans);
 82         }
 83         else{
 84             int l=read()-1,r=l+1;
 85             numl=l/len,numr=r/len;
 86             posl=l%len,posr=r%len;
 87             int lc=s[numl].a[posl],rc=s[numr].a[posr];
 88             if(lc==rc){
 89                 continue;
 90             }
 91             vector<int>::iterator it;
 92             it=lower_bound(s[numl].v.begin(),s[numl].v.end(),lc);
 93             s[numl].v.erase(it);
 94             it=lower_bound(s[numl].v.begin(),s[numl].v.end(),rc);
 95             s[numl].v.insert(it,rc);
 96             it=lower_bound(s[numr].v.begin(),s[numr].v.end(),rc);
 97             s[numr].v.erase(it);
 98             it=lower_bound(s[numr].v.begin(),s[numr].v.end(),lc);
 99             s[numr].v.insert(it,lc);
100             swap(s[numl].a[posl],s[numr].a[posr]);
101 //            for(int i=0;i<=num;i++){
102 //                for(int j=0;j<s[i].v.size();j++){
103 //                    printf("%d ",s[i].v[j]);
104 //                }
105 //                printf("\n");
106 //            }
107 //            printf("\n");
108         }
109     }
110     return 0;
111 }

分桶

其实直接记录下每个数字出现的位置放到vector里面然后二分一下就可以了,

思路很简单,正如管理员说的“很多人学数据结构学傻了”,简单的问题不需要那么麻烦的

不过这题有个小坑,编号指的就是从左向右数第几个,不是兔子的属性

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<vector>
 6 #define MAXN 300005
 7 using namespace std;
 8 int n;
 9 vector<int> s[MAXN];
10 int read(){
11     int x=0;char ch=getchar();
12     while(ch<‘0‘||ch>‘9‘){ch=getchar();}
13     while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
14     return x;
15 }
16 void write(int x){
17     if(!x){
18         putchar(48);
19         putchar(‘\n‘);
20         return;
21     }
22     char t[10]={0};
23     int cnt=0;
24     while(x){
25         t[++cnt]=x%10;
26         x/=10;
27     }
28     for(int i=cnt;i>=1;i--){
29         putchar(48+t[i]);
30     }
31     putchar(‘\n‘);
32 }
33 int a[MAXN];
34 int main()
35 {
36 //    freopen("color2.in","r",stdin);
37     n=read();
38     int T=read();
39     for(int i=1;i<=n;i++){
40         a[i]=read();
41         s[a[i]].push_back(i);
42     }
43     while(T--){
44         int p=read();
45         if(p==1){
46             int l=read(),r=read(),c=read();
47             write(upper_bound(s[c].begin(),s[c].end(),r)-lower_bound(s[c].begin(),s[c].end(),l));
48         }
49         else{
50             int l=read(),r=l+1;
51             if(a[l]==a[r]){
52                 continue;
53             }
54             int P1=lower_bound(s[a[l]].begin(),s[a[l]].end(),l)-s[a[l]].begin();
55             int P2=lower_bound(s[a[r]].begin(),s[a[r]].end(),r)-s[a[r]].begin();
56             s[a[l]][P1]=r;
57             s[a[r]][P2]=l;
58             swap(a[l],a[r]);
59         }
60     }
61     return 0;
62 }

AC

有点卡常

总的来说这题出的还算不错的,很灵活的数据结构

时间: 2024-11-07 12:11:25

洛谷mNOIP模拟赛Day1-数颜色的相关文章

【洛谷mNOIP模拟赛Day1】T1 斐波那契

题目传送门:https://www.luogu.org/problemnew/show/P3938 这题出得特别吼啊~~ 通过打表或者大胆猜想斐波那契数列的一些性质,我们不难发现对于一只兔子$x$,其父亲必为$x-Fk$($F$为斐波那契数列,且$F_{k}$为不大于$x$的最大数字),举个例子:$7-5=2$,$11-8=3$,对于点$x$和点$y$,我们分别求出其所有直系祖宗,然后扫一遍即可. 由于斐波那契数列为指数级增长,故向上跳的复杂度为一个$log$级别,时间复杂度为$O(m*log(

洛谷mNOIP模拟赛Day1-斐波那契

题目背景 大样例下发链接:http://pan.baidu.com/s/1c0LbQ2 密码:jigg 题目描述 小 C 养了一些很可爱的兔子. 有一天,小 C 突然发现兔子们都是严格按照伟大的数学家斐波那契提出的模型来进行 繁衍:一对兔子从出生后第二个月起,每个月刚开始的时候都会产下一对小兔子.我们假定, 在整个过程中兔子不会出现任何意外. 小 C 把兔子按出生顺序,把兔子们从 1 开始标号,并且小 C 的兔子都是 1 号兔子和 1 号兔子的后代.如果某两对兔子是同时出生的,那么小 C 会将父

洛谷mNOIP模拟赛Day2-将军令

题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 历史/落在/赢家/之手 至少/我们/拥有/传说 谁说/败者/无法/不朽 拳头/只能/让人/低头 念头/却能/让人/抬头 抬头/去看/去爱/去追 你心中的梦 题目描述 又想起了四月. 如果不是省选,大家大概不会这么轻易地分道扬镳吧? 只见一个又一个昔日的队友离开了机房. 凭君莫话封侯事,一将功成万骨枯. 梦里,小 F 成了一个给将军送密信的信使. 现在,有两封关乎国家生死的密信需要送到前

洛谷mNOIP模拟赛Day1-分组

传送门 首先是贪心的思路 从后向前选,能多选就多选, 理由:数字越少肯定越优,同时间隔尽量向前推,字典序尽量小 对于K==1,枚举1~512直接判断 对于K==2,需要用镜像并查集,来刻画"敌对关系",如果a和b产生矛盾,就把a和b的镜像(b')连接 ,b和a'连接,然后判断自己是不是和自己的镜像连接了 打上时间戳避免清零卡常 1 #include<cstdio> 2 #include<cstdlib> 3 #include<algorithm> 4

洛谷mNOIP模拟赛Day2-入阵曲

题目背景 pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 丹青千秋酿,一醉解愁肠. 无悔少年枉,只愿壮志狂. 题目描述 小 F 很喜欢数学,但是到了高中以后数学总是考不好. 有一天,他在数学课上发起了呆:他想起了过去的一年.一年前,当他初识算法竞赛的 时候,觉得整个世界都焕然一新.这世界上怎么会有这么多奇妙的东西?曾经自己觉得难以 解决的问题,被一个又一个算法轻松解决. 小 F 当时暗自觉得,与自己的幼稚相比起来,还有好多要学习的呢. 一年过

洛谷OJ P1045 麦森数 解题报告

洛谷OJ P1045 麦森数 解题报告 by MedalPluS   题目描述 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它有909526位.麦森数有许多重要应用,它与完全数密切相关. 任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示)   输入描述   文件中只包含一个整数P(1000&l

NOI模拟赛 Day1

[考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧张起来!!! 好了不扯淡了...

【mNOIP模拟赛Day 1】 T2 数颜色

题目传送门:https://www.luogu.org/problemnew/show/P3939 题外话:写完这题后本地跑了下极限数据,用时1.5s,于是马上用fread+fwrite优化至0.3s,交至OJ,跑了600+ms,好奇地去掉fread和fwrite,居然只跑了700+ms(总感觉哪里不太对劲). 此题有一个性质:对于一个点i,其有且只有一只兔子,且该兔子的颜色是唯一的.考虑到数据范围较小(兔子数量和颜色数量均$\leq 3*10^{5}$),我们可以对所有颜色开一棵线段树,维护该

计蒜客NOIP模拟赛D2T3 数三角形

刚刚上高中的洁洁在学习组合数学的过程中遇到一道麻烦的题目,她希望你能帮助她解决.给定一张无向完全图 G,其中大部分边被染成蓝色,但也有一些边被染成红色或者绿色.现在,洁洁需要给这张图的多样性进行打分.一张图的多样性取决于它的同色和异色三角形的个数.具体来说,G 中每有一个三边颜色都互不同的三角形(异色三角形)可以得 3 分,每有一个三边颜色都相同的三角形(同色三角形)则要被扣掉 6 分,其它三角形不得分也不扣分. 现在,请你写一个程序来计算 G 的多样性分数.输入格式 第一行两个正整数 n 和