1. 程式人生 > 實用技巧 >maven 打包時自定義變數的使用

maven 打包時自定義變數的使用

單調佇列

#include<bits/stdc++.h>
using namespace std;
deque<int> q;
int a[10000000];
int main(){
	int n,k;
	cin >>n >>k;
	for(int i=1;i<=n;i++)
	{
		cin >>a[i];
	}
	for(int i=1;i<=n;i++)
	{
		while(!q.empty()&&q.front()<=i-k)q.pop_front();
		while(!q.empty()&&a[i]<a[q.back()])q.pop_back();
		q.push_back(i);
		if(i-k>=0)cout << a[q.front()] << " ";
	}
	cout <<endl;
	while(!q.empty())q.pop_front();
	for(int i=1;i<=n;i++)
	{
		while(!q.empty()&&q.front()<=i-k)q.pop_front();
		while(!q.empty()&&a[i]>a[q.back()])q.pop_back();
		q.push_back(i);
		if(i-k>=0)cout << a[q.front()] << " ";
	}
}

快速冪

記得隨時取模。

#include<bits/stdc++.h>
using namespace std;
long long b,p,k;
long long apow(int a,int b)
{
	long long ans=1;
	while(b)
	{
		if(b&1)
		{
			ans=((ans%k)*(a%k))%k;
		}
		a=((a%k)*(a%k))%k;
		b=b>>1;
	}
	return ans%k;
}
int main(){
	cin >> b >> p >> k;
	cout << b<<"^"<<p<<" mod "<< k<< "="<< apow(b,p)%k;
}

並查集

記得初始化f陣列啊( )

#include<bits/stdc++.h>
using namespace std;
int n,m,p;
int f[200086];
int find(int x)
{
	if(f[x]==x)return x;
	return f[x]=find(f[x]);//路徑壓縮
}
void hb(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
	f[fx]=fy;
	return ;
}
void solve(){
	cin >> n >> m ;
	for(int i=1;i<=n;i++)
	{
		f[i]=i;
	}
	while(m--)
	{
		int z,x,y;
		cin >> z >> x >> y;
		if(z==1)
		hb(x,y);
		else
		{
			if(find(x)==find(y))
			{
				cout << "Y" << endl;
			}
			else
			{
				cout << "N" << endl;
			}
		}
	}
	return;
}
int main()
{
	solve();
	return 0;
}

樹狀陣列

維護一些有字首性質的東西

#include<iostream>
using namespace std;
int tr[10000000];
int n,m;
int lowbit(int x)//返回最低位的1
{
	return x&(-x);	
}
void plu(int pl,int val)
{
	for(;pl<=n;pl+=lowbit(pl))//+lowbit到一個包含於它的更大區間
	{
		tr[pl]+=val;
	}
	return;
}
void inputDa()
{
	cin >> n >> m;
	for(int i=1;i<=n;i++)
	{
		int j;
		cin >> j;
		plu(i,j);
	}
}
int su(int x,int y)
{
	int su=0;
	for(;y;y-=lowbit(y))//-lowbit到一個不包含它的極大區間
	{
		su+=tr[y];
	}
	for(;x;x-=lowbit(x))
	{
		su-=tr[x];
	}
	return su;
}
void solve(){
	for(int i=1;i<=m;i++)
	{
		int j;
		cin >> j;
		if(j==1)
		{
			int x,k;
			cin >> x >> k;
			plu(x,k);
		}
		else
		{
			int x,y;
			cin >> x >> y;
			cout << su(x-1,y) << endl;
		}
	}
}
int main()
{
	inputDa();
	solve();
	return 0;
}

Kruskal

最小生成樹的比較快的演算法(應該比加了堆優化的prim快吧)

#include<bits/stdc++.h>
using namespace std;
int n,m,ans;
int f[50086];
struct edge{
	int u,v,val;
};
edge e[2000086];

bool cmp(edge x,edge y)
{
	return x.val < y.val;
}

int find(int x)
{
	if(f[x]==x)return x;
	return f[x]=find(f[x]);
}

void hb(int x,int y)
{
	int fx=find(x);
	int fy=find(y);
	if(fx!=fy)
	f[fx]=fy;
	return ;
}

void inputData()
{
    cin >> n >> m ;
    //如果m<n-1必然不連通 
	if(m<n-1)
	{
		cout << "orz";
		return;
	}
	//並查集初始化 
	for(int i=1;i<=n;i++)
	{
		f[i]=i;
	}
	
	for(int i=1;i<=m;i++)
	{
		int x,y,v;
		cin >> x >> y >> v;
		e[i].u=x;
		e[i].v=y;
		e[i].val=v;
	}
}
void solve(){
	sort(e+1,e+m+1,cmp);
	int num=1,i=0;//num記錄當前的邊,i記錄有效合併 
	while(i<n-1)//當i=n-1的時候合併完成 
	{
		if(num>m)//如果所有的邊都用了還不能完成合並,說明圖不連通 
		{
			cout << "orz";
			return;
		}
		
		int u,v,dis;
		u=e[num].u;
		v=e[num].v;
		dis=e[num].val;
		num++;

		if(find(u)==find(v))//如果連通就繼續迴圈 
		{
			continue;
		}
		else//否則合併並記錄答案 
		{
			hb(u,v);
			i++;
			ans+=dis;
		}
	}
	cout << ans;
	return;
}
int main()
{
	inputData();
	solve();
	return 0;
}

dij

跑純最短路時比較快的演算法

不能處理負環(SPFA,請)

懶惰刪除聽說加不加無所謂,最好加上吧

#include<bits/stdc++.h>
using namespace std;
typedef struct{int v,w;} abc;//v編號,w存ans
struct node{
	int to,nxt,val;
};
node e[600100],d[600100];
int num,n,m,a,s,ans[200100];
abc x;
bool vis[200100];
priority_queue <abc> q;//存值
bool operator<(const abc&a,const abc &b) {return a.w>b.w;}
void ins(int u,int v,int val)//插入操作
{
	num++;
	e[num].to=v;
	e[num].val=val;
	e[num].nxt=d[u].nxt;
	d[u].nxt=num;
	return ;
}
void inputDa()
{
	cin >> n >> m >> s;//n個點,m條邊
	for(int i=1;i<=m;i++)
	{
		int u,v,val;
		cin >> u >> v >> val;
		ins(u,v,val);
	}
}
void find()//找出距離原點最近的
{
    if(!q.empty())
    {
        x=q.top();
        q.pop();
    }
	return;
}
void clr()
{
	for(int i=1;i<=n;i++)
	{
		ans[i]=(1<<31)-1;
	}
}
void dij()
{
    x.v=s;
    x.w=0;
    q.push(x);
    ans[s]=0;
	while(!q.empty())//一共n個點,每個點都被找出一次
	{
		find();//找離原點最近的點
        if(vis[x.v])continue;//懶惰刪除
        vis[x.v]=1;
		//cout << x.v << " " << x.w << endl;
		for(int i=d[x.v].nxt;i;i=e[i].nxt)
		{ 
			ans[e[i].to]=min(ans[e[i].to],ans[x.v]+e[i].val);//遍歷並更新
			if(vis[e[i].to]==0)
			{
				abc tmp;
                tmp.v=e[i].to;
                tmp.w=ans[e[i].to];
				q.push(tmp);
			}
		}
	}
    return;
}
void outputAns(){
    for(int i=1;i<=n;i++)
    {
        cout << ans[i] << " ";
    }
}
int main()
{
	inputDa();
    clr();
	dij();
	outputAns();
	return 0;
}