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_2a1≤a1b1≤b2c1>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]);}
}
2021“MINIEYE杯”中国大学生算法设计超级联赛(1)zoto(二维数颜色)相关推荐
- 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(3)签到题3题
2021"MINIEYE杯"中国大学生算法设计超级联赛(3) Start Time : 2021-07-27 12:00:00 End Time : 2021-07-27 17:0 ...
- 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(1)签到题15869
2021"MINIEYE杯"中国大学生算法设计超级联赛(1) Start Time : 2021-07-20 12:10:00 End Time : 2021-07-20 17:1 ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛
2021"MINIEYE杯"中国大学生算法设计超级联赛 1006 Given a sequence of integers of length n, find the shorte ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(2)
2021"MINIEYE杯"中国大学生算法设计超级联赛(2) 1008 I love exam (类背包DP) 1010 I love permutation (数学构造,剩余系) ...
- 7068 Dota2 Pro Circuit 杭电多校(2021“MINIEYE杯”中国大学生算法设计超级联赛9) [贪心+双指针]
题目 Dota2 Pro Circuit *Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Oth ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(1)个人解题报告
文章目录 HDU6950 Mod, Or and Everything HDU6954 Minimum spanning tree HDU6958 KD-Graph HDU6957 Maximal s ...
- 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(5)签到题4题
Solved Pro.ID Title Ratio(Accepted / Submitted) 1001 Miserable Faith 33.33%(19/57) 1002 String Mod 2 ...
- 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(8)
1006 GCD Game (博弈论,nim游戏,质因子个数) 题意:有n个数a1,a2....an两个人玩游戏,Alice先动,Bob后动每次可以将一个数变为他的因子,直到不能动就输了. 题解:将问 ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(8)(1002,1004,1006,1009)
前言 依旧是白嫖账号,只打了一些题/kk 正题 1002 Buying Snacks 题目大意 nnn个物品,每个可以买一次也可以不买,如果买需要选择1/21/21/2块钱的,然后也可以相邻两个一起买 ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(7)部分题解
前言 找大佬嫖到个号来划水打比赛了,有的题没写或者不是我写的就不放了. 目前只有:1004,1005,1007,1008,1011 正题 题目链接:https://acm.hdu.edu.cn/con ...
最新文章
- EntityFramework用法探索(一)DatabaseFirst
- linux bashrc与profile的区别
- 光有面罩不是能防护的
- 用户操作-登录代码实现
- 利用 Celery 构建 Web 服务的后台任务调度模块
- centos7安装3.6版本zookeeper和jdk8
- iOS开发 - ARC的开启与关闭
- 《深度学习Python实践》第14章——自动流程
- AMD上线Linux专版驱动17.10:支持最新API接口
- kotlin学习二:初步认识kotlin
- iPad中国内地商标权诉讼调查
- 病毒RNA分离:病毒RNA提取试剂盒方案
- 个人公众号注销方法_微信公众号注销后怎么申请 恢复公众号的方法步骤
- linux无法访问移动硬盘,移动硬盘“无法访问”的解决方案
- windows打开iis7服务器远程桌面管理器
- Python类传参报错-TypeError:takes 2 positional arguments but 3 were given
- 耐心排序之最长递增子序列(LIS)
- 订单查询系统c语言作业,C语言设计订单管理系统答题.doc
- Fedora安装字体方法和Ubuntu非常不同!
- 有什么软件可以测试面膜的好坏,检验面膜好坏的小妙招
热门文章
- mysql中查询出现的错误_在MySQL查询中查询语法错误
- ntopng mysql_网络流量监控工具与分析Ntop和Ntopng
- [Spring5]IOC容器_Bean管理XML方式_注入其他类型属性
- C++二维数组作为函数参数
- 在O(1)的时间内计算n个整数落在区间[a,b]的个数(预处理时间为O(n+k))
- Redis高效性探索--线程IO模型,通信协议
- python2字符串编码方式_一、基础部分-2.字符串编码
- 数据结构:链表(c语言)
- Hebbian principle理解
- Georgia and Bob(Poj 1704)Nim 博弈