Home avatar

白衣苍狗

单调队列

单调队列

(以单调递增队列为例)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
template<typename T,int maxnode,bool comp(const T&,const T&) >
struct upQUE
{
	T ary[maxnode+1];
	int f,t;
	int cnt=0;
	upQUE(){f=t=cnt=0;}
	void clear(){f=t=cnt=0;}
	bool empty(){return cnt==0;}
	T front(){return ary[f];}
	T tail(){return t==0?ary[maxnode]:ary[t-1];}
	void push(const T& w)
	{
		while(t!=f&&comp(w,tail()))
		{
			--t;
			if(t==-1)t=maxnode;
		}
		ary[t++]=w;
		if(t==maxnode+1)t=0;
		++cnt;
	}

	void pop()
	{
		++f;
		if(f==maxnode+1)f=0;
		--cnt;
	}
};

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//heap
template<typename T,bool comp(const T& a,const T& b)>
struct HEAP
{
	T ary[maxnode];
	int f;
	HEAP(){f=0;}
	bool empty(){return f==0;}
	void push(const T& w)
	{
		ary[++f]=w;
		for(int k=f;k!=1&&comp(ary[k],ary[k/2]);k/=2)
		{
			Swap(ary[k],ary[k/2]);
		}
	}
	T top(){return ary[1];}
	T pop()
	{
		T tmp=ary[1];
		ary[1]=ary[f--];
		for(int k=1,son=k*2;son<=f;k=son,son=k*2)
		{
			if(son+1<=f&&comp(ary[son+1],ary[son]))
				++son;
			if(comp(ary[son],ary[k]))
				Swap(ary[k],ary[son]);
			else break;
		}
		return tmp;
	}
};

链表

链表

普通双向链表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//list
const int maxnode=10003;
template<typename T>
struct LIST
{
	int pre[maxnode],nxt[maxnode];
	T ary[maxnode];
	int f;
	int endd;
	LIST()
	{
		f=0;
		endd=maxnode-1;
		nxt[0]=endd;
	}
	void clear()
	{
		f=0;
		endd=maxnode-1;
		nxt[0]=endd;
	}
	void insert(int k,const T& w)//insert in front of k
	{
		ary[++f]=w;
		int pree=pre[k],nxtt=k;
		pre[nxtt]=nxt[pree]=f;
		nxt[f]=nxtt;
		pre[f]=pree;
	}
	void del(int k)
	{
		int pree=pre[k],nxtt=nxt[k];
		pre[nxtt]=pree;
		nxt[pree]=nxtt;
	}
	int begin()
	{
		return nxt[0];
	}
	int end()
	{
		return endd;
	}
};

支持内存回收的双向链表

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
template<typename T,int size>
struct QUE
{
	T ary[size];
	int f,t,cnt;
	QUE(){f=t=cnt=0;}
	void clear(){f=t=cnt=0;}
	bool empty(){return cnt==0;}
	void push(const T& w)
	{
		ary[t++]=w;
		if(t==size)t=0;
		++cnt;
	}
	T top(){return ary[f];}
	void pop()
	{
		++f,--cnt;
		if(f==size)f=0;
	}
};
template<typename T,int size>
struct memLIST
{
	 T ary[size+1];
	 int pre[size+1],nxt[size+1];
	 int f;
	 QUE<int,size> mem;
	 int endd;
	 memLIST()
	 {
	 	memset(pre,0,sizeof(pre));
	 	memset(nxt,0,sizeof(nxt));
	 	f=0;
	 	mem.clear();
	 	nxt[0]=endd;
	 	endd=size;
	 }
	 void clear()
	 {
	 	memset(pre,0,sizeof(pre));
	 	memset(nxt,0,sizeof(nxt));
	 	f=0;
	 	mem.clear();
	 	nxt[0]=endd;
	 	endd=size;
	 }
	 T operator[](int k)
	 {
	 	return ary[k];
	 }
	 void del(int k)
	 {
	 	int pree=pre[k],nxtt=nxt[k];
	 	nxt[pree]=nxtt;
	 	pre[nxtt]=pree;
	 	pre[k]=nxt[k]=0;
	 	mem.push(k);
	 }
	 void insert(const T& w,int k)//insert in front of k
	 {
	 	int id;
	 	if(!mem.empty())
		 	id=mem.top(),mem.pop();
	 	else id=++f;
	 	int pree=pre[k],nxtt=k;
	 	pre[id]=pree;
	 	nxt[id]=nxtt;
	 	nxt[pree]=pre[nxtt]=id;
	 	ary[id]=w;
	 }
	 int begin()
	 {
	 	return nxt[0];
	 }
	 int end()
	 {
	 	return endd;
	 }
};

最短路

最短路算法

Floyd

SPFA

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;

const int maxn=103;
const int maxm=23;
const int maxe=maxm*maxm*2;
const int INF=2e9;

int n,m,k,e,x,y,z,d,p,a,b;
int tot,point[maxm],nxt[maxe],v[maxe],c[maxe];
int dis[maxm];
bool vis[maxm],flag[maxm];
queue <int> q;

inline void addedge(int x,int y,int z)
{
    ++tot;
    nxt[tot]=point[x];
    point[x]=tot;
    v[tot]=y;
    c[tot]=z;
    ++tot;
    nxt[tot]=point[y];
    point[y]=tot;
    v[tot]=x;
    c[tot]=z;
}
inline int spfa()
{
    memset(dis,0x7f,sizeof(dis));
    dis[1]=0;
    memset(vis,0,sizeof(vis));
    vis[1]=true;
    while (!q.empty()) q.pop();
    q.push(1);

    while (!q.empty())
    {
        int now=q.front();
        q.pop();
        vis[now]=false;
        for (int i=point[now]; i; i=nxt[i])
            if (dis[v[i]]>dis[now]+c[i]&&!flag[v[i]])
            {
                dis[v[i]]=dis[now]+c[i];
                if (!vis[v[i]])
                {
                    vis[v[i]]=true;
                    q.push(v[i]);
                }
            }
    }
    return dis[m];
}

Dijkstra

例题:hdu2544

动态规划——悬线法

动态规划——悬线法

例题:USACO 6.1.2 rectbarn

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
ID:du331691
PROG:rectbarn
LANG:C++
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
template<typename T>
void read(T& w)
{
	char r;
	for(r=getchar();r<48||r>57;r=getchar());
	for(w=0;r>=48&&r<=57;r=getchar())w=w*10+r-48;
}
template<typename T>
T Min(const T& a,const T& b){return a<b?a:b;}
template<typename T>
T Max(const T& a,const T& b){return a>b?a:b;}
const int maxn=3003;
const int maxp=30003;
int n,m,p;
bool tree[maxn][maxn];
int height[2][maxn];
int treel[2][maxn],treer[2][maxn];
int Left[2][maxn],Right[2][maxn];
void input()
{
	read(n),read(m),read(p);
	int x,y;
	for(int i=1;i<=p;++i)
	{
		read(x),read(y);
		tree[x][y]=true;
	}

}
int ans=0;
void dp()
{
	for(int j=1;j<=m;++j)
		tree[0][j]=tree[n+1][j]=true;
	for(int i=2;i<=n-1;++i)
	{
		tree[i][0]=tree[i][m+1]=true;
	}
	
	for(int i=1;i<=n;++i)
	{
		int now=i&1,lst=i&1^1;
				
		for(int j=1,last=0;j<=m;++j)
		{
			if(tree[i][j])
				last=j;
			treel[now][j]=last;
		}
		for(int j=m,last=m+1;j>=1;--j)
		{
			if(tree[i][j])
				last=j;
			treer[now][j]=last;
		}
		for(int j=1;j<=m;++j)
		{
			if(tree[i-1][j])
			{
				height[now][j]=1;
				Left[now][j]=treel[now][j];
				Right[now][j]=treer[now][j];
			}
			else
			{
				height[now][j]=height[lst][j]+1;
				Left[now][j]=Max(treel[now][j],Left[lst][j]);
				Right[now][j]=Min(treer[now][j],Right[lst][j]);
			}
			if(!tree[i][j])
			{
				int tans=(Right[now][j]-Left[now][j]-1)*height[now][j];
				if(tans>ans)
					ans=tans;
			}
		}

	}
}
int main()
{
	freopen("rectbarn.in","r",stdin);
	freopen("rectbarn.out","w",stdout);
	input();
	dp();
	printf("%d\n",ans);
	return 0;
}

参考资料

国家集训队2003论文集-王知昆

最小表示法

最小表示法

例题:luogu1709USACO5.5.2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
ID:du331691
PROG:hidden
LANG:C++
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cctype>
using namespace std;
const int maxn=100003*2;
int n;
char s[maxn];
void input()
{
	scanf("%d",&n);
	for(int i=0;i<n;++i)
	{
		char r;
		do{r=getchar();}
		while(!islower(r));
		s[i]=s[i+n]=r;
	}
}
int ans;
void solve()
{
	int i=0,j=1;
	while(j<=n)
	{
		bool ok=true;
		for(int k=0;k<=n-1&&ok;++k)
		{
			if(s[i+k]!=s[j+k])
			{
				ok=false;
				if(s[i+k]>s[j+k])
					i=i+k+1;
				else j=j+k+1;
			}
		}
		if(ok)
		{
			ans=i;
			return;
		}
		if(i==j)++j;
	}
	ans=i;
}
int main()
{
	freopen("hidden.in","r",stdin);
	freopen("hidden.out","w",stdout);
	input();
	solve();
	printf("%d\n",ans);
	return 0;
}

参考资料

0%