2021“MINIEYE杯”中国大学生算法设计超级联赛(1)zoto(二维数颜色)

zoto

Code1

树状数组套动态开点权值线段树
效仿HH的项链,维护右端点,询问需要排序

#include<bits/stdc++.h>
using namespace std;
template <class T=int> T rd()
{T res=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res;
}
const int N=100010;
int a[N],n,m,ans[N],last[N];
struct nodeq
{int l,r,L,R,id;bool operator<(const nodeq& o)const{return r<o.r;}
}q[N];
struct node
{int l,r,v;
}tree[N*200];
int rt[N],cnt;
void update(int &u,int l,int r,int pos,int v)
{if(!u) tree[u=++cnt]={0,0,0};tree[u].v+=v;if(l==r) return;int mid=l+r>>1;if(pos<=mid) update(tree[u].l,l,mid,pos,v);if(pos>mid)  update(tree[u].r,mid+1,r,pos,v);
}
int query(int u,int l,int r,int L,int R)
{if(!u) return 0;if(L<=l&&r<=R) return tree[u].v;int mid=l+r>>1;int v=0;if(L<=mid) v+=query(tree[u].l,l,mid,L,R);if(R>mid) v+=query(tree[u].r,mid+1,r,L,R);return v;
}
int lowbit(int x){return x&-x;}
void add(int k,int pos,int v)
{for(;k<=n;k+=lowbit(k)) update(rt[k],0,100000,pos,v);
}
int ask(int k,int L,int R)
{int ans=0;for(;k;k-=lowbit(k)) ans+=query(rt[k],0,100000,L,R);return ans;
}void init()
{for(int i=1;i<=100000;i++) last[i]=0;for(int i=1;i<=n;i++) rt[i]=0;cnt=0;for(int i=0;i<=cnt;i++) tree[i].l=tree[i].r=tree[i].v=0;
}
int main()
{int Tc=rd();while(Tc--){init();n=rd(),m=rd();for(int i=1;i<=n;i++) a[i]=rd();for(int i=1;i<=m;i++){int x0=rd(),y0=rd(),x1=rd(),y1=rd();q[i]={x0,x1,y0,y1,i};}sort(q+1,q+1+m);int k=1;for(int i=1;i<=m;i++){for(;k<=q[i].r;k++){int v=a[k];if(last[v]) add(last[v],v,-1);add(k,v,1);last[v]=k;}ans[q[i].id]=ask(q[i].r,q[i].L,q[i].R)-ask(q[i].l-1,q[i].L,q[i].R);}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);}
}

Code2

树状数组套动态开点权值线段树
校dl的写法,不需要对询问进行排序

#include<bits/stdc++.h>
using namespace std;
template <class T=int> T rd()
{T res=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res;
}
const int N=100010;
int a[N],n,m,ans[N],last[N];
struct nodeq
{int l,L,R,id;
};
vector<nodeq> q[N];
struct node
{int l,r,v;
}tree[N*200];
int rt[N],cnt,lim;
void update(int &u,int l,int r,int pos,int v)
{if(!u) u=++cnt;tree[u].v+=v;if(l==r) return;int mid=l+r>>1;if(pos<=mid) update(tree[u].l,l,mid,pos,v);if(pos>mid)  update(tree[u].r,mid+1,r,pos,v);//tree[u].v=tree[tree[u].l].v+tree[tree[u].r].v;
}
int query(int u,int l,int r,int L,int R)
{if(!u) return 0;if(L<=l&&r<=R) return tree[u].v;int mid=l+r>>1;int v=0;if(L<=mid) v+=query(tree[u].l,l,mid,L,R);if(R>mid) v+=query(tree[u].r,mid+1,r,L,R);return v;
}
int lowbit(int x){return x&-x;}
void add(int k,int pos,int v)
{for(;k<=n;k+=lowbit(k)) update(rt[k],0,lim,pos,v);
}
int ask(int k,int L,int R)
{int ans=0;for(;k;k-=lowbit(k)) ans+=query(rt[k],0,lim,L,R);return ans;
}
void init()
{for(int i=0;i<=lim;i++) last[i]=0;for(int i=0;i<=n;i++) rt[i]=0;for(int i=0;i<=cnt;i++) tree[i].l=tree[i].r=tree[i].v=0;cnt=0;for(int i=0;i<=n;i++) q[i].clear();
}
int main()
{int Tc=rd();while(Tc--){init();n=rd(),m=rd();for(int i=1;i<=n;i++) a[i]=rd();lim=*max_element(a+1,a+1+n);for(int i=1;i<=m;i++){int x0=rd(),y0=rd(),x1=rd(),y1=rd();q[x1].push_back({x0,y0,y1,i});}for(int i=1;i<=n;i++){if(last[a[i]]) add(last[a[i]],a[i],-1);add(i,a[i],1);last[a[i]]=i;for(auto t:q[i])ans[t.id]=ask(i,t.L,t.R)-ask(t.l-1,t.L,t.R);}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);}
}

Code3

std写法

首先来看一个子问题:给一个数组,初始所有位置全是0,每次单点加一或减一,询问区间有多少个位置不为0。也许你很快会给出一个修改O(logn)查询O(logn)的优秀做法。那么如果强制规定修改O(1),查询能做到什么效率?我们去考虑分块,维护两个数组num[i]和sum[i]分别维护第i位置上的值,以及第i块内的值不为0的位置个数。那么每次单点修改只需要修改num[i]和sum[i/block_size]两个位置的值,然后查询的时候需要O(sqrtn)效率的去查询区间所覆盖的完整块的值以及区间两端散块的值(散块值可以没有)。这显然是一个修改O(1),查询O(sqrtn)的做法。
然后考虑这个题,我们发现可以用莫队去维护询问的区间,即x坐标。y(fx)维度单独拎出来就变成了上述子问题。我们会神奇的发现,这样的复杂度是:O(nsqrt(n)1+m1sqrt(n))的,莫队单次修改时O(sqrtn)的复杂度遇上了值域上O(1)的修改,莫队单次查询时O(1)的复杂度遇上了值域查询时O(sqrt(n))的复杂度。

#include<bits/stdc++.h>using namespace std;
using ll=long long;
template <class T=int> T rd()
{T res=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res;
}
const int N=100010;
int a[N],n,m;int b[N],sz;
struct nodeq
{int l,r,L,R,id;bool operator<(const nodeq&o)const{if(b[l]==b[o.l]){if(b[l]&1)return r<o.r;elsereturn r>o.r;}return b[l]<b[o.l];}
}q[N];
int num[N],sum[N],ans[N];
void add(int k){if(++num[k]==1) sum[b[k]]++;}
void sub(int k){if(--num[k]==0) sum[b[k]]--;}
int query(int k)
{int res=0;for(int i=1;i<b[k];i++) res+=sum[i];for(int i=(b[k]-1)*sz+1;i<=k;i++) res+=(num[i]>=1);return res;
}
int main()
{int Tc=rd();while(Tc--){n=rd(),m=rd(),sz=313;for(int i=1;i<=n;i++) a[i]=rd();for(int i=1;i<=n;i++) sum[i]=num[i]=0;for(int i=1;i<=n;i++) b[i]=(i-1)/sz+1;for(int i=1;i<=m;i++){int x0=rd(),y0=rd(),x1=rd(),y1=rd();q[i]={x0,x1,y0,y1,i};}sort(q+1,q+1+m);int l=1,r=0;for(int i=1;i<=m;i++){while(l<q[i].l) sub(a[l++]);while(l>q[i].l) add(a[--l]);while(r<q[i].r) add(a[++r]);while(r>q[i].r) sub(a[r--]);ans[q[i].id]=query(q[i].R)-query(q[i].L-1);}for(int i=1;i<=m;i++) printf("%d\n",ans[i]);}
}

Code4

把种类查询转换偏序查询的常规操作:指向上一个出现的位置当且仅当上一次出现的位置在区间外面时计算贡献

cdq分治+bit
对于每个询问的右端点也看作一个时间轴,如果该点可能对询问产生贡献,那么下一个这个点的横坐标严格大于询问右端点。
a1≤a1b1≤b2c1>c2a_1\leq a_1\\ b_1\leq b_2 \\c_1>c_2a1a1b1b2c1>c2
cdq分治转化为平面二维数点,然后差分+bit即可统计。


对于每个询问的左端点也看作一个时间轴,如果该点可能对询问产生贡献,那么前一个这个点的横坐标严格小于询问左端点。

本质都种类→\to偏序

#include<bits/stdc++.h>
using namespace std;
template <class T=int> T rd()
{T res=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res;
}
const int N=100010;
int a[N],n,m,ans[N],last[N];
int ne[N],pos[N];
struct nodeq
{int op;int a,b,c;int fg,id;
}q[N<<4];
int fw[N];
int lowbit(int x){return x&-x;}
void update(int k,int v){for(;k<=n+1;k+=lowbit(k)) fw[k]+=v;}
int qsum(int k){int v=0;for(;k;k-=lowbit(k)) v+=fw[k];return v;}void solve(int l,int r)
{if(l>=r) return;int mid=l+r>>1;solve(l,mid),solve(mid+1,r);int i=l;for(int j=mid+1;j<=r;j++){while(i<=mid&&q[i].b<=q[j].b) {if(q[i].op==0) update(q[i].c,1);i++;}if(q[j].op==1) ans[q[j].id]+=q[j].fg*(qsum(n+1)-qsum(q[j].c));}while(i>l) {--i;if(q[i].op==0) update(q[i].c,-1);}inplace_merge(q+l,q+mid+1,q+r+1,[](const nodeq&x,const nodeq&y){return x.b<y.b||x.b==y.b&&x.a<y.a;});
}
int main()
{int Tc=rd();while(Tc--){n=rd(),m=rd();for(int i=1;i<=n;i++) a[i]=rd();for(int i=1;i<=m;i++) ans[i]=0;for(int i=0;i<=100000;i++) pos[a[i]]=n+1;for(int i=n;i>=1;i--) {ne[i]=pos[a[i]];pos[a[i]]=i;}int cnt=0;for(int i=1;i<=n;i++) q[++cnt]={0,i,a[i],ne[i]};for(int i=1;i<=m;i++){int x0=rd(),y0=rd(),x1=rd(),y1=rd();q[++cnt]={1,x0-1,y0-1,x1,1,i};q[++cnt]={1,x0-1,y1,x1,-1,i};q[++cnt]={1,x1,y0-1,x1,-1,i};q[++cnt]={1,x1,y1,x1,1,i};}sort(q+1,q+1+cnt,[](const nodeq&x,const nodeq&y){return x.a<y.a||x.a==y.a&&x.b<y.b;});solve(1,cnt);for(int i=1;i<=m;i++) printf("%d\n",ans[i]);}
}

Code5

和Code4基本一样

#include<bits/stdc++.h>
using namespace std;
template <class T=int> T rd()
{T res=0;char ch=getchar();while(!isdigit(ch)) ch=getchar();while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();return res;
}
const int N=100010;
int a[N],n,m,ans[N];
int last[N],pos[N];
struct nodeq
{int op;int a,b,c;int fg,id;
}q[N<<4];
int fw[N];
int lowbit(int x){return x&-x;}
void update(int k,int v){if(!k) return fw[k]+=v,void();for(;k<=n;k+=lowbit(k)) fw[k]+=v;}
int qsum(int k){int v=fw[0];for(;k;k-=lowbit(k)) v+=fw[k];return v;}void solve(int l,int r)
{if(l>=r) return;int mid=l+r>>1;solve(l,mid),solve(mid+1,r);int i=l;for(int j=mid+1;j<=r;j++){while(i<=mid&&q[i].b<=q[j].b) {if(q[i].op==0) update(q[i].c,1);i++;}if(q[j].op==1) ans[q[j].id]+=q[j].fg*qsum(q[j].c);}while(i>l) {--i;if(q[i].op==0) update(q[i].c,-1);}inplace_merge(q+l,q+mid+1,q+r+1,[](const nodeq&x,const nodeq&y){return x.b<y.b||x.b==y.b&&x.a<y.a;});
}
int main()
{int Tc=rd();while(Tc--){n=rd(),m=rd();for(int i=1;i<=n;i++) a[i]=rd();for(int i=1;i<=m;i++) ans[i]=0;for(int i=0;i<=100000;i++) pos[a[i]]=0;for(int i=1;i<=n;i++) {last[i]=pos[a[i]];pos[a[i]]=i;}int cnt=0;for(int i=1;i<=n;i++) q[++cnt]={0,i,a[i],last[i]};for(int i=1;i<=m;i++){int x0=rd(),y0=rd(),x1=rd(),y1=rd();q[++cnt]={1,x0-1,y0-1,x0-1,1,i};q[++cnt]={1,x0-1,y1,x0-1,-1,i};q[++cnt]={1,x1,y0-1,x0-1,-1,i};q[++cnt]={1,x1,y1,x0-1,1,i};}sort(q+1,q+1+cnt,[](const nodeq&x,const nodeq&y){return x.a<y.a||x.a==y.a&&x.b<y.b;});solve(1,cnt);for(int i=1;i<=m;i++) printf("%d\n",ans[i]);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318866.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通过Microsoft Learn进行学习以提升技能

通过 Microsoft Learn&#xff0c;可以免费而且轻松有趣地学习 Microsoft 技术。Microsoft Learn的与众不同借助 Microsoft Learn&#xff0c;任何人都能按自己的学习计划和速度掌握重要的知识和概念。 使用者将能够访问培训资料、代码示例&#xff0c;以及免费试用产品。无论是…

牛客练习赛84F-牛客推荐系统开发之下班【莫比乌斯反演,杜教筛】

正题 题目链接:https://ac.nowcoder.com/acm/contest/11174/F 题目大意 给出n,kn,kn,k求 ∑i11n∑i21n...∑ik1ngcd(fi1,fi2,...,fik)\sum_{i_11}^n\sum_{i_21}^n...\sum_{i_k1}^ngcd(f_{i_1},f_{i_2},...,f_{i_{k}})i1​1∑n​i2​1∑n​...ik​1∑n​gcd(fi1​​,fi2​​,.…

牛客题霸 [旋转字符串]C++题解/答案

牛客题霸 [旋转字符串]C题解/答案 题目描述 字符串旋转: 给定两字符串A和B&#xff0c;如果能将A从中间某个位置分割为左右两部分字符串&#xff08;都不为空串&#xff09;&#xff0c;并将左边的字符串移动到右边字符串后面组成新的字符串可以变为字符串B时返回true。 例如…

震惊!递推与递归竟然可以这么编!%99的程序员都不知道!

四、归并排序&#xff08;逆序对&#xff09; (一)、归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b; 即先使…

asp.net core webApi 参数保护

Introasp.net core data protection 扩展&#xff0c;基于 IDataProtector 扩展的数据保护组件&#xff0c;自动化的实现某些参数的保护ParamsProtectionParamsProtection 是为了保护 asp.net core webapi 项目的某些参数而设计的&#xff0c;也可以用来做一定程度上的反爬虫。…

2021牛客暑期多校训练营2 J-Product of GCDs(数论+计数)

J-Product of GCDs Code1 对于每个质数以及每个质数的次幂单独考虑他们的贡献&#xff0c;由于多次使用快速幂导致TLE #include<bits/stdc.h> using namespace std; using lllong long; template <class Tint> T rd() {T res0;T fg1;char chgetchar();while(!is…

AT2390-[AGC016F]Games on DAG【状压dp,SG函数】

正题 题目链接:https://www.luogu.com.cn/problem/AT2390 解题思路 nnn个点的DAGDAGDAG&#xff0c;mmm条边可有可无&#xff0c;111和222上有石头。求有多少种方案使得先手必胜。 1≤n≤15,1≤m≤n(n−1)21\leq n\leq 15,1\leq m\leq \frac{n(n-1)}{2}1≤n≤15,1≤m≤2n(n−1…

牛客题霸 [合并两个有序的数组] C++题解/答案

牛客题霸 [合并两个有序的数组] C题解/答案 题目描述 给出两个有序的整数数组 和 &#xff0c;请将数组 合并到数组 中&#xff0c;变成一个有序的数组 注意&#xff1a; 可以假设 数组有足够的空间存放 数组的元素&#xff0c; 和 中初始的元素数目分别为 和 题目描述 给出…

震惊!快速幂怎么编?省一说暴力,银牌说递归,国集听完笑了

国集&#xff1a;打表啊&#xff01;&#xff01; 题目描述 给你三个整数 b,p,kb,p,kb,p,k&#xff0c;求 bp mod kb^p \bmod kbpmodk。 输入格式 输入只有一行三个整数&#xff0c;分别代表 b,p,kb,p,kb,p,k 输出格式 输出一行一个字符串 b^p mod ks&#xff0c;其中 b,…

CF1392G-Omkar and Pies【dp】

正题 题目链接:https://www.luogu.com.cn/problem/CF1392G 题目大意 两个长度为kkk的起始和目标01串。 nnn个操作交换起始串的两个位置&#xff0c;选择一段长度至少为mmm的连续操作序列使得相同的位数最多。 1≤m≤n≤106,1≤k≤201\leq m\leq n\leq 10^6,1\leq k\leq 201≤…

codeforces1484 B. Restore Modulo(数学)

B. Restore Modulo 忘了当时怎么乱搞的了~ #include<bits/stdc.h>using namespace std; using lllong long;constexpr int N200010;int n; ll a[N],d[N],d0[N]; int main() {ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);int T1;cin>>T;whil…

牛客题霸 [反转字符串] C++题解/答案

牛客题霸 [反转字符串] C题解/答案 题目描述 写出一个程序&#xff0c;接受一个字符串&#xff0c;然后输出该字符串反转后的字符串。&#xff08;字符串长度不超过1000&#xff09; 题解&#xff1a; 有reverse现成的翻转函数&#xff0c;直接套进去就可以 如果不用函数的…

新汉诺塔(洛谷P1242)含第11个数据的解决办法

解析 应该从大到小一个个移&#xff0c;这样后面大盘就可以直接忽略&#xff0c;保证没有冗余操作&#xff0c;必定最优&#xff08;如果先移动小的&#xff0c;后面移动大的时还要动小的&#xff09; 对于第id个从当前位置到目标的移动有两种移动方案&#xff1a; 法1&#x…

让 .Net 更方便的导入导出Excel

Intro因为前一段时间需要处理一些 excel 数据&#xff0c;主要是导入/导出操作&#xff0c;将 Excel 数据转化为对象再用程序进行处理和分析&#xff0c;没有找到比较满意的库&#xff0c;于是就自己造了一个轮子&#xff0c;屏蔽掉了 xlsx 与 xls 的差别&#xff0c;屏蔽了 Np…

P7115-[NOIP2020]移球游戏【构造】

正题 题目链接:https://www.luogu.com.cn/problem/P7115 题目大意 n1n1n1个柱子&#xff0c;前面nnn个上面各有mmm个球&#xff0c;球有nnn种颜色&#xff0c;每种mmm个。 你每次可以把一个柱子最上面的球放到另一个上面&#xff0c;要求在820000820000820000次内使得同种颜色…

2021牛客暑期多校训练营1 I-Increasing Subsequence(期望dp+优化)

I-Increasing Subsequence fi,j,0/1f_{i,j,0/1}fi,j,0/1​表示上一轮第一个人选了iii&#xff0c;第二个人选了jjj&#xff0c;并且当前是第1/2个人选择的概率。 转移考虑枚举k下一步往哪走 fi,k,1∑fi,j,0/cntf_{i,k,1}\sum f_{i,j,0}/ \text{cnt}fi,k,1​∑fi,j,0​/cnt fk,…

牛客题霸 [子数组的最大累加和问题] C++题解/答案

牛客题霸 [子数组的最大累加和问题] C题解/答案 题目描述 给定一个数组arr&#xff0c;返回子数组的最大累加和 例如&#xff0c;arr [1, -2, 3, 5, -2, 6, -1]&#xff0c;所有子数组中&#xff0c;[3, 5, -2, 6]可以累加出最大的和12&#xff0c;所以返回12. [要求] 时间复…

无限序列 (ybtoj C.3)

解析 乍一看很蒙的题 首先&#xff0c;a-b1的个数可以等价于**&#xff08;1-b&#xff09;1的个数减去&#xff08;1-a-1&#xff09;1的个数** 分析之后发现&#xff0c;经过多次变换后&#xff1a; 长度 1的个数 1 1 2 1 3 2 5 3 8 5 … … 又是熟悉的斐波拉契。。。 但是我…

P5644-[PKUWC2018]猎人杀【NTT,分治】

正题 题目链接:https://www.luogu.com.cn/problem/P5644 题目大意 nnn个人&#xff0c;每个人被选中的权重是aia_iai​。每次按照权重选择一个没有死掉的人杀死&#xff0c;求第111个人最后死的概率。输出答案对998244353998244353998244353取模。 wi>0,∑i1nwi≤105w_i>…

对传统应用进行容器化改造

本文由 陈计节 翻译自 FP Complete 网站上的文章 CONTAINERIZING A LEGACY APPLICATION: AN OVERVIEW&#xff0c;原作者 Emanuel Borsboom。以下为译文全文&#xff0c;如需阅读英文原文&#xff0c;请转到文末获取链接&#xff1a;本文接下来简要介绍什么是容器化&#xff0c…