当前位置:网站首页>8/3 训练日志 (树状数组+区间覆盖+思维+01字典树)
8/3 训练日志 (树状数组+区间覆盖+思维+01字典树)
2022-08-04 12:33:00 【钟钟终】
P5149 会议座位
又看了一遍树状数组,通透了好多。
思路:
1.采用字典树统计记录单词原本的次序,再记录调换后的次序
2.采用树状数组求出逆序对。(本质只求正序对)
大小写敏感,26*2=52个字符,可能有52 个分支,最大5层
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=5e5+5;
const int inf=0x3f3f3f3f;
int n,a[N];
int ch[N][55],idx,cnt[N],tree[N];
char s[N];
void ins(char *s,int rk)
{
int p=0;
for(int i=0;s[i];i++)
{
int j=s[i]-'a';
if(!ch[p][j]) ch[p][j]=++idx;
p=ch[p][j];
}
cnt[p]=rk;
}
int query(char *s)
{
int p=0;
for(int i=0;s[i];i++)
{
int j=s[i]-'a';
p=ch[p][j];
}
return cnt[p];
}
int lowbit(int x){
return x&(-x);}
void add(int x,int k)
{
for(;x<=n;x+=lowbit(x))
tree[x]+=k;
}
int qry(int x)
{
int tmp=0;
for(;x>=1;x-=lowbit(x))
tmp+=tree[x];
return tmp;
}
signed main()
{
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s;
ins(s,i);
}
for(int i=1;i<=n;i++)
{
cin>>s;
a[i]=query(s);
}
int ans=0;
for(int i=1;i<=n;i++)
{
add(a[i],1);
ans+=i-qry(a[i]);
}
cout<<ans<<endl;
return 0;
}
D. Color with Occurrences
思路:
1.思路并不复杂,代码要注意的细节较多。考察的知识点是贪心、区间覆盖问题。
2.先枚举各个字符串能匹配的区间,包含左右端点,隶属的id号。
3.在将区间排序。对于每个区间,找到相同起点能覆盖的最远的段。
具体可看代码理解,细节较多。
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N =1e6+100;
const int mod=998244353;
string t,s;
int n,cnt;
struct node
{
int l,r,id;
}e[N];
bool cmp(node e1,node e2)
{
if(e1.l==e2.l) return e1.r<e2.r;
return e1.l<e2.l;
}
vector<pair<int,int>>ans;
signed main()
{
int q;cin>>q;
while(q--)
{
ans.clear();cnt=0;
cin>>t;cin>>n;
int len_t=t.length();
for(int i=1;i<=n;i++)
{
cin>>s;int len_s=s.length();
for(int j=0;j<len_t-len_s+1;j++)
{
int flag=1;
for(int k=0;k<len_s;k++)
{
if(s[k]!=t[k+j])
{
flag=0;break;
}
}
if(flag)
{
e[++cnt].l=j+1;
e[cnt].r=j+len_s-1+1;
e[cnt].id=i;
}
}
}
sort(e+1,e+cnt+1,cmp);
int now=1,l=-1,r=0,g,f1=1;
while(r<len_t)
{
l=r+1;
for(int i=now;i<=cnt;i++)
{
if(e[i].l<=l&&e[i].r>=l)
{
if(e[i].r>r)
{
r=e[i].r;g=i;
}
}
else if(e[i].l>l)
{
now=i;break;
}
}
if(r<l)
{
f1=0;break;
}
ans.push_back({
e[g].id,e[g].l});
}
if(!f1)
{
cout<<-1<<endl;continue;
}
cout<<ans.size()<<endl;
for(int i=0;i<ans.size();i++)
cout<<ans[i].first<<" "<<ans[i].second<<endl;
}
return 0;
}
E. Choosing The Commander
题意:每个士兵都有一个个性值,给定一个长官的pi和li,使得x^pi<li,统计满足条件得士兵个数。
思路:
1.操作1和2,分表在字典树中添加一个数和删去一个数
2.预处理出每个数字经过各个idx的数量
3.分别枚举pi和li得二进制位,ans加上pi和x异或值为0的数量,再将p指向异或为1的方向,因为下面可能还会有满足条件的士兵。
ps:编号p指向0的边表示为ch[p][0]
,指向1的边表示为ch[p][1]
出现编号为0,要及时退出。这很重要
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=3e6+5;
const int inf=0x3f3f3f3f;
int n,a[N];
int ch[N][2],idx,sum[N];
void ins(int x)
{
int p=0; //作为起始编号,无实际意义
for(int i=31;i>=0;i--)
{
int j=x>>i&1;
if(!ch[p][j]) ch[p][j]=++idx;
p=ch[p][j];
sum[p]++;
}
}
void del(int x)
{
int p=0;
for(int i=31;i>=0;i--)
{
int j=x>>i&1;
p=ch[p][j];
sum[p]--;
}
}
int query(int x,int y)
{
int p=0,res=0; //p在j的上一层
for(int i=31;i>=0;i--)
{
int a=x>>i&1;
int b=y>>i&1;
if(b)
{
res+=sum[ch[p][a]];
p=ch[p][1-a];
}
else
p=ch[p][a];
if(!p) break; //若不写会wa2
}
return res;
}
signed main()
{
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
int q;cin>>q;
while(q--)
{
int g;cin>>g;
if(g==1)
{
int x;cin>>x;ins(x);
}
else if(g==2)
{
int x;cin>>x;del(x);
}
else
{
int x,y;cin>>x>>y;
cout<<query(x,y)<<endl;
}
}
return 0;
}
01字典树
经典问题:最大异或对
题意:给定一个数组,任选两个数进行异或,得到的最大数是多少
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N=3e5+5;
const int inf=0x3f3f3f3f;
int n,a[N];
int ch[N*31][2],idx;
void ins(int x)
{
int p=0; //作为起始编号,无实际意义
for(int i=30;i>=0;i--)
{
int j=x>>i&1;
if(!ch[p][j]) ch[p][j]=++idx;
p=ch[p][j];
}
}
int query(int x)
{
int p=0,res=0; //p在j的上一层
for(int i=30;i>=0;i--)
{
int j=x>>i&1;
if(ch[p][!j]) //走相反位
{
res+=1<<i;p=ch[p][!j];
}
else
p=ch[p][j];
if(!p) break; //若不写会wa2
}
return res;
}
int main()
{
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i],ins(a[i]);
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,query(a[i]));
cout<<ans<<endl;
return 0;
}
P4551 最长异或路径
性质:x ^y ^y=x
(一个数,如果它两次异或同一个数,那么它是不会有改变的)
因此,i~j的路径上的异或和,
就可以表示成 根到i的异或和 ^ 根到j的异或和
。
思路:
1.预处理出根到各个点的异或值。
2.对异或值建立01字典树
3.查询取出极大值。
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N=3e5+5;
const int inf=0x3f3f3f3f;
int n,a[N];
int ch[N*31][2],idx,head[N],cnt,sum[N];
struct node
{
int to,nxt,w;
}e[N];
void add(int from,int to,int w)
{
e[++cnt].to=to;
e[cnt].nxt=head[from];
e[cnt].w=w;
head[from]=cnt;
}
void dfs(int u,int fa)
{
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v!=fa)
{
sum[v]=sum[u]^e[i].w;
dfs(v,u);
}
}
}
void ins(int x)
{
int p=0; //作为起始编号,无实际意义
for(int i=30;i>=0;i--)
{
int j=x>>i&1;
if(!ch[p][j]) ch[p][j]=++idx;
p=ch[p][j];
}
}
int query(int x)
{
int p=0,res=0; //p在j的上一层
for(int i=30;i>=0;i--)
{
int j=x>>i&1;
if(ch[p][!j]) //走相反位
{
res+=1<<i;p=ch[p][!j];
}
else
p=ch[p][j];
if(!p) break; //若不写会wa2
}
return res;
}
int main()
{
std::cin.tie(nullptr);
std::ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<n;i++)
{
int u,v,w;cin>>u>>v>>w;
add(u,v,w),add(v,u,w);
}
dfs(1,0);
for(int i=1;i<=n;i++)
ins(sum[i]);
int ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,query(sum[i]));
cout<<ans<<endl;
return 0;
}
边栏推荐
- 技术分享| 小程序实现音视频通话
- 力扣每日一题-第48天-345. 反转字符串中的元音字母
- MySQL必知必会(初级篇)
- 【软考 系统架构设计师】软件架构设计② 软件架构风格
- 《独行月球》猛药,治不了开心麻花内耗
- ReentrantLock 原理
- Two years of independent development experience Programmers tell us the experience of making money (listen to the masters who really make money)
- 1314元的七夕礼盒,收割了多少直男?
- 企业应当实施的5个云安全管理策略
- The head module of the yolo series
猜你喜欢
“蔚来杯“2022牛客暑期多校训练营4 N
持续交付(四)Jenkins多线程任务执行
break与continue超详解!!!
Hit the interview!The latest interview booklet of Ali Jin, nine silver and ten is stable!
开发小程序插件如何实现盈利?
Cool and efficient data visualization big screen, it's really not that difficult to do!丨Geek Planet
Motion Rule (16)-Union Check Basic Questions-Grid Game
【微信小程序】信息管理与信息系统专业社会实习制作项目--垃圾指纹
聚焦数据来源、数据质量和模型性能构建小微企业信用画像
手搓一个“七夕限定”,用3D Engine 5分钟实现烟花绽放效果
随机推荐
考研概率论与数理统计(知识点梳理)
移动跨端技术方案分析对比
A Collection of Flutter Tutorials (2022 Edition)
Launcher app prediction
云原生Devops 的实现方法
常用代码模板1——基础语法
【水一个徽章】
简要介绍电源效率测试
微信小程序使用腾讯云对象储存上传图片
倒计时 3 天|一起看云原生 Meetup 的六大议题
ShanDong Multi-University Training #4 A、B、C、G
【PHP实现微信公众平台开发—基础篇】第1章 课程介绍
【黑马早报】尚乘数科上市13天,市值超阿里;北大终止陈春花聘用合同;新东方花近200亿退学费和遣散费;张小泉75%产品贴牌代工...
Nacos手摸手教学【二】Nacos注册中心
【PHP实现微信公众平台开发—基础篇】第2章 微信公众账号及申请流程详解
飞书更新招聘功能 候选人可选择面试时间
Neck modules of the yolo series
ES 节点2G内存分析
一分钟认识 IndexedDB 数据库,太强大了!
【Game Of AutoTest】1、再度启程,重识游戏自动化测试