1,莫队算法:eg1:rmq problem;eg2:小z的袜子;2,dfs中的连通性:eg1:acwing 1112.迷宫;eg2:acwing 1113.红与黑;3,dfs之搜索顺序:eg1:acwing 1116. 马走日;
1,莫队;
eg1:rmq problem;
add:添加元素,我们添加这个元素之后,判断与当前答案是否相等,若相等就让当前答案一直增加,直到不存在这个元素。
sub:删除元素,我们删除这个元素之后,直接与当前答案取个最小值即可。
但是最后一个数据会tle掉:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(ll i=a;i<n;++i)
#define rep2(i,a,n) for(ll i=a;i<=n;++i)
#define per1(i,n,a) for(ll i=n;i>a;i--)
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double dob;
const int N=2e5+10;
int n,m,k;
int pos[N];
int cnt[N];
struct ji
{
int l,r,xh;
}q[N];
bool cmp(ji a,ji b)
{
return pos[a.l]==pos[b.l]?a.r<b.r:pos[a.l]<pos[b.l];
}
int ans[N];
int a[N];
int res;
void add(int i)
{
cnt[a[i]]++;
if(cnt[a[i]]==1)
{
int t=a[i];
if(t==res)
{
while(++t)
{
if(!cnt[t])
{
res=t;
return ;
}
}
}
}
}
void sub(int i)
{
cnt[a[i]]--;
if(!cnt[a[i]])res=min(res,a[i]);
}
signed main()
{
quick_cin();
cin>>n>>m;
int siz=sqrt(n);
rep2(i,1,n)
{
cin>>a[i];
pos[i]=i/siz;
}
rep2(i,1,m)
{
cin>>q[i].l>>q[i].r;
q[i].xh=i;
}
sort(q+1,q+m+1,cmp);
int l=1,r=0;
rep2(i,1,m)
{
while(q[i].l<l)add(--l);
while(q[i].r>r)add(++r);
while(q[i].l>l)sub(l++);
while(q[i].r<r)sub(r--);
ans[q[i].xh]=res;
}
rep2(i,1,m)cout<<ans[i]<<endl;
return 0;
}
eg2:小z的袜子;
用莫队维护的性质需要能推,所以推样例找规律;
拿2,6看,分子是C(2,2)+C(3,2)
分母是C(5,2);
所以分母很好求,len*(len-1)/2;
重要的是分子的维护:
分子是区间内的各个颜色的数量取2个的方案数的和;
观察C(2,2)=1,C(3,2)=3,C(4,2)=6,C(5,2)=10;
每次增加一个数目,它的方案数增加之前的个数;
所以借此维护一个sum,来做分子;
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register ll i=a;i<n;++i)
#define rep2(i,a,n) for(register ll i=a;i<=n;++i)
#define per1(i,n,a) for(register ll i=n;i>a;i--)
#define per2(i,n,a) for(register ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef pair<int,int> PII;
typedef pair<long long,long long>PLL;
typedef pair<int,PII> PIII;
typedef long long ll;
typedef double dob;
const int N=1e5+5;
int pos[N],cnt[N],a[N];
ll res;
PLL ans[N];
int n,m;
ll sum;
struct ji
{
int l,r,xh;
}q[N];
int kuai,quan;
bool cmp(ji a,ji b)
{
if(pos[a.l]==pos[b.l])return a.r<b.r;
return pos[a.l]<pos[b.l];
}
void add(int i)
{
sum+=cnt[a[i]];
cnt[a[i]]++;
}
void sub(int i)
{
cnt[a[i]]--;
sum-=cnt[a[i]];
}
PLL zjfs(ll a,ll b)
{
while(__gcd(a,b)!=1)
{
ll x=__gcd(a,b);
a/=x;
b/=x;
}
return {a,b};
}
signed main()
{
quick_cin();
cin>>n>>m;
kuai=sqrt(n);
rep2(i,1,n)
{
cin>>a[i];
pos[i]=i/kuai;
}
rep2(i,1,m)
{
int l,r;
cin>>l>>r;
q[i]={l,r,(int)i};
}
sort(q+1,q+m+1,cmp);
int l=1,r=0;
rep2(i,1,m)
{
while(q[i].l<l)add(--l);
while(q[i].r>r)add(++r);
while(q[i].l>l)sub(l++);
while(q[i].r<r)sub(r--);
if(l==r)
ans[q[i].xh]={0,1};
else
{
int len=r-l+1;
if(!sum)ans[q[i].xh]={0,1};
else
{
//cout<<sum<<" "<<len*(len-1)/2<<endl;
auto t=zjfs(sum,(ll)len*(len-1)/2);
ans[q[i].xh]={t.yi,t.er};
}
}
}
rep2(i,1,m)cout<<ans[i].yi<<"/"<<ans[i].er<<endl;
return 0;
}
eg3:easy string problem
2,dfs中的连通性:
连通性的问题一般dfs和bfs都可,但bfs稳定,dfs有爆栈的风险;
但dfs代码求两个点是否连通,写起来代码简洁,短,能更快的ac;
eg1:迷宫;
解法一:bfs
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(ll i=a;i<n;++i)
#define rep2(i,a,n) for(ll i=a;i<=n;++i)
#define per1(i,n,a) for(ll i=n;i>a;i--)
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double dob;
const int N=110;
char a[N][N];
int st[N][N];
int n;
int xa,xb,ya,yb;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
bool bfs()
{
queue<PII>q;
q.push({xa,ya});
st[xa][ya]=1;
if(a[xa][ya]=='#'||a[xb][yb]=='#')return 0;
if(xa==xb&&ya==yb)return 1;
while(q.size())
{
auto t=q.front();
q.pop();
rep1(i,0,4)
{
int x=t.yi+dx[i],y=t.er+dy[i];
if(a[x][y]!='#'&&st[x][y]==0&&x>-1&&x<n&&y>-1&&y<n)
{
st[x][y]=1;
q.push({x,y});
if(x==xb&&y==yb)return 1;
}
}
}
return 0;
}
void solve()
{
memset(st,0);
cin>>n;
rep1(i,0,n)
rep1(j,0,n)cin>>a[i][j];
cin>>xa>>ya>>xb>>yb;
if(bfs())yes;
else no;
}
signed main()
{
quick_cin();
int T;
cin>>T;
while(T--)solve();
return 0;
}
解法二:dfs()
dfs注意特判顺序!!;
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(ll i=a;i<n;++i)
#define rep2(i,a,n) for(ll i=a;i<=n;++i)
#define per1(i,n,a) for(ll i=n;i>a;i--)
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double dob;
const int N=110;
char g[N][N];
int st[N][N];
int n,m;
int xa,xb,ya,yb;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
bool dfs(int x,int y)
{
if(g[x][y]=='#')return 0;
if(x==xb&&y==yb)return 1;
st[x][y]=1;
rep1(i,0,4)
{
int a=x+dx[i],b=y+dy[i];
if(a>-1&&a<n&&b>-1&&b<n&&g[a][b]=='.'&&st[a][b]==0)
{
if(dfs(a,b))return 1;
}
}
return 0;
}
void solve()
{
cin>>n;
memset(st,0);
rep1(i,0,n)
rep1(j,0,n)
cin>>g[i][j];
cin>>xa>>ya>>xb>>yb;
if(dfs(xa,ya))yes;
else no;
}
signed main()
{
quick_cin();
int T;
cin>>T;
while(T--)solve();
return 0;
}
eg2:红与黑;
解法一:bfs;
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(ll i=a;i<n;++i)
#define rep2(i,a,n) for(ll i=a;i<=n;++i)
#define per1(i,n,a) for(ll i=n;i>a;i--)
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double dob;
const int N=110;
char a[N][N];
int st[N][N];
int n,m;
int sx,sy;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int bfs()
{
queue<PII>q;
q.push({sx,sy});
st[sx][sy]=1;
int num=1;
while(q.size())
{
auto t=q.front();
q.pop();
rep1(i,0,4)
{
int x=t.yi+dx[i],y=t.er+dy[i];
if(a[x][y]=='.'&&st[x][y]==0&&x>-1&&x<n&&y>-1&&y<m)
{
st[x][y]=1;
q.push({x,y});
num++;
}
}
}
return num;
}
signed main()
{
quick_cin();
while(cin>>m>>n,n,m)
{
memset(st,0);
rep1(i,0,n)
rep1(j,0,m)
{
cin>>a[i][j];
if(a[i][j]=='@')sx=i,sy=j;
}
int ans=bfs();
cout<<ans<<endl;
}
return 0;
}
解法二:dfs();
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(ll i=a;i<n;++i)
#define rep2(i,a,n) for(ll i=a;i<=n;++i)
#define per1(i,n,a) for(ll i=n;i>a;i--)
#define per2(i,n,a) for(ll i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pb push_back
#define endl "\n"
#define lowbit(m) (-m&m)
#define yes cout<<"YES\n"
#define no cout<<"NO\n"
#define yi first
#define er second
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef double dob;
const int N=110;
char g[N][N];
int st[N][N];
int n,m;
int xa,xb,ya,yb;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int dfs(int x,int y)
{
int cnt=1;
st[x][y]=1;
rep1(i,0,4)
{
int a=x+dx[i];
int b=y+dy[i];
if(a<0||a>n-1||b<0||b>m-1)continue;
if(st[a][b])continue;
if(g[a][b]!='.')continue;
cnt+=dfs(a,b);
}
return cnt;
}
signed main()
{
quick_cin();
while(cin>>m>>n,n,m)
{
int x,y;
rep1(i,0,n)
rep1(j,0,m)
{
cin>>g[i][j];
if(g[i][j]=='@')
{
x=i;
y=j;
}
}
memset(st,0);
cout<<dfs(x,y)<<endl;
}
return 0;
}
3,dfs搜索顺序;
eg1:马走日;
题意:
主要的棋盘很小,所以dfs暴搜;
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rep1(i,a,n) for(register int i=a;i<n;++i)
#define rep2(i,a,n) for(register int i=a;i<=n;++i)
#define per1(i,n,a) for(register int i=n;i>a;i--)
#define per2(i,n,a) for(register int i=n;i>=a;i--)
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define memset(a,i) memset((a),(i),sizeof (a))
#define memcpy(a,i) memcpy((a),(i),sizeof (a))
#define pro_q priority_queue
#define pb push_back
#define pf push_front
#define endl "\n"
#define lowbit(m) (-m&m)
#define YES cout<<"YES\n"
#define NO cout<<"NO\n"
#define Yes cout<<"Yes\n"
#define No cout<<"No\n"
#define yes cout<<"yes\n"
#define no cout<<"no\n"
#define yi first
#define er second
using namespace std;
typedef pair<int,int> PII;
typedef pair<long long,long long>PLL;
typedef pair<int,PII> PIII;
typedef long long ll;
typedef double dob;
const int N=110;
int st[N][N];
int sx,sy,n,m;
int ans;
int dx[]={-2,-1,1,2,2,1,-1,-2};
int dy[]={1,2,2,1,-1,-2,-2,-1};
void dfs(int x,int y,int cnt)
{
if(cnt==n*m)
{
ans++;
return;
}
st[x][y]=1;
rep1(i,0,8)
{
int a=x+dx[i];
int b=y+dy[i];
if(a>-1&&b>-1&&a<n&&b<m&&st[a][b]==0)
dfs(a,b,cnt+1);
}
st[x][y]=0;
}
signed main()
{
quick_cin();
int T;
cin>>T;
while(T--)
{
memset(st,0);
ans=0;
cin>>n>>m;
cin>>sx>>sy;
dfs(sx,sy,1);
cout<<ans<<endl;
}
return 0;
}