22/5/17

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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dull丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值