ACM 模板

template<class T> inline void rd(T &x)
{
    x=0;char o,f=1;
    while(o=getchar(),o<48)if(o==45)f=-f;
    do x=(x<<3)+(x<<1)+(o^48);
    while(o=getchar(),o>47);
    x*=f;
}

数论

快速幂

typedef long long ll;
ll quickpow(ll a,ll n,ll p) //a^n%p;
{
	ll ans = 1;
	while(n)
	{
		if(n&1) ans = ans * a % p;
		a = a * a %p;
		n >>= 1;
	}
	return ans;
}

欧几里得

int gcd(int a,int b)
{
	if(b==0)return a;
	return gcd(b,a%b);
}
int lcm(int a,int b)
{
	return a/gcd(a,b)*b;
}

扩展欧几里得

(1)求解不定方程;
(2)求解模线性方程(线性同余方程);
(3)求解模的逆元;

int exgcd(int a,int b,int &x,int &y)
{
	if(b==0) {
		x = 1;
		y = 0;
		return a;
	}
	int r = exgcd(b,a%b,x,y);
	int t = x;
	x = y;
	y = t-a/b*y;
	return r;
}

最小生成树

·prim

const int maxn = 505;
const int INF = 0x3f3f3f3f;
bool vis[maxn];
int lowc[maxn];
int cost[maxn][maxn];
int prim()
{
	int asn = 0;
	memset(vis,false,sizeof(vis));
	vis[0] = true;
	for(int i = 1;i < n;i++) lowc[i] = cost[0][i];
	for(int i = 1;i < n;i++)
	{
		int minc = INF;
		int p = -1;
		for(int j = 0;j < n;j++)
			if(!vis[j]&&minc > low[j])
			{
				minc = lowc[j];
				p = j;
			}
		if(minc == INF) return -1;
		ans+=minc;
		for(int j = 0;j < n;j++)
			if(!vis[j]&&lowc[j]>cost[p][j])
				lowc[j] = cost[p][j];
	}
	return ans;
}

最短路径

· 单源最短路径 迪杰斯特拉 Dijkstra

堆优化

const int maxn = 505;
vector<pair<int,int> > E[maxn];
priority_queue<pair<int,int> > q;
int pre[maxn];
bool vis[maxn];
int dis[maxn];
int s,d;//s为开始节点.
void dijkstar()
{
	dis[s] = 0;
	q.push(make_pair(-dis[s],s));
	while(!q.empty())
	{
		int t = q.top().second;
		q.pop();
		if(vis[t])
			continue;
		vis[t] = true;
		for(int i = 0;i < E[t].size();i++)
		{
			int to = E[t][i].first;
			int di = E[t][i].second;
			if(dis[to] > dis[t]+di)
			{
				dis[to] = dis[t]+di;
				pre[to] = t;
				q.push(make_pair(-dis[to],to);
			}
		}
	}
}

强连通分量

·Tarjan

const int maxn = 5e5+5;
vector<int> ep[maxn];
vector<int> bel[maxn];
stack<int> s;
int cnt,cntb;
int dfn[maxn];
int low[maxn];
int belong[maxn];
int out[maxn];
bool in_stack[maxn];
void Tarjan(int u)
{
	dfn[u] = low[u] = ++cnt;
	s.push(u);
	in_stack[u] = true;
	for(int i = 0;i < ep[u].size();i++)
	{
		int v = ep[u][i];
		if(!dfn[v])
		{
			Tarjan(v);
			low[u] = min(low[u],low[v]);
		}
		else if(in_stack[v])
				low[u] = min(low[u],dfn[v]);
	}
	if(dfn[u] == low[u])
	{
		++cntb;
		int node;
		do
		{
			node = s.top();
			s.pop();
			in_stack[node] = false;
			belong[node] = cntb;
			bel[cntb].push_back(node);
		}while(node!=u);
	}
}

·Kosaraju

·树状数组

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e5+5;
int c[maxn];
int a[maxn];
int n;
int lowbit(int x)
{
    return x&(-x);
}
void Update(int i,int k)//在i位置上的值加k
{
    while(i<=n)
    {
        c[i]+=k,i+=lowbit(i);
    }
}
int sum(int x)//求a[1...x]的和
{
    int ret=0;
    while(x)
    {
        ret+=c[x],x-=lowbit(x);
    }
    return  ret;
}
int main()
{
    cin >> n;
    for(int i = 1;i <= n;i++)
    {
        cin >> a[i];
        Update(i,a[i]);
    }
    cout << sum(n)<<endl;
    return 0;
}

Manacher

#include <bits/stdc++.h>

using namespace std;
const int maxn = 1e3+5;

int p[maxn*2];

string Manacher(string s)
{
    string t= "$#";
    for(int i = 0;i < s.size();i++)
    {
        t+=s[i];
        t+="#";
    }
    int mx = 0,id=0,reslen=0,rescenter=0;
    for(int i =1;i < t.size();i++)
    {
        p[i]=mx>id?min(p[2*id-i],mx-i):1;
        while(t[i+p[i]]==t[i-p[i]])p[i]++;
        if(i+p[i]>mx)
        {
            mx=i+p[i];
            id=i;
        }
        if(p[i]>reslen)
        {
            reslen=p[i];
            rescenter=i;
        }

    }
    return s.substr((rescenter-reslen)/2,reslen-1);
}
int main()
{
    string s;
    getline(cin,s);
    string t = Manacher(s);
    cout << t.size()<<endl;
    return 0;
}

线段树

//#include <bits/stdc++.h>
//
//using namespace std;
//const int maxn = 1e5+5;
//typedef long long ll;
//typedef unsigned long long ull;
//struct node{
//    ll sum,lazy;
//};
//int n,m;
//int a[maxn];
//node t[4*maxn];
//void change(int x,int tl,int tr,int p,int k)//单点修改p位置加k
//{
//    if(tl==tr)
//    {
//        t[x].sum+=k;
//        return;
//    }
//    int mid = (tl+tr)>>1;
//    if(p<=mid)change(2*x,tl,mid,p,k);
//    else change(2*x+1,mid+1,r,p,k);
//    t[x].sum=t[2*x].sum+t[2*x+1].sum;
//}
//void update(int x,int tl,int tr)
//{
//    t[x].sum = t[x].sum+(tr-tl+1)*t[x].lazy;
//    if(tl!=tr)
//    {
//        t[2*x].lazy+=t[x].lazy;
//        t[2*x+1].lazy+=t[x].lazy;
//    }
//    t[x].lazy=0;
//}
//void change(int x,int tl,int tr,int l,int r,int k)
//{
//    if(tl==l&&tr==r)
//    {
//        t[x].lazy+=k;
//        return;
//    }
//    if(t[x].lazy)update(x,tl,tr);
//    int mid = (tl+tr)>>1;
//    if(r<=mid)change(2*x,tl,mid,l,r,k);
//    else if(l>mid)change(2*x+1,mid+1,tr,l,r,k);
//    else{
//        change(2*x,tl,mid,l,mid,k);
//        change(2*x+1,mid+1,tr,mid+1,r,k);
//    }
//    t[x].sum=t[2*x].sum+(mid-tl+1)*t[2*x].lazy+t[2*x+1].sum+(tr-mid)*t[2*x+1].lazy;
//}
//ll ask(int x,int tl,int tr,int l,int r)//查询[l,r]的和
//{
//    if(tl==l&&tr==r) return t[x].sum;
//    int mid = (tl+tr)>>1;
//    if(r<=mid)return ask(2*x,tl,mid,l,r);
//    else if(l>mid)return ask(2*x+1,mid+1,tr,l,r);
//    else{
//        return ask(2*x,tl,mid,l,mid)+ask(2*x+1,mid+1,tr,mid+1,r);
//    }
//}
//void build(int x,int l,int r)
//{
//    if(l==r)
//    {
//        t[x].sum=a[l];
//        return ;
//    }
//    int mid = (l+r)>>1;
//    build(2*x,l,mid);
//    build(2*x+1,mid+1,r);
//    t[x].sum = t[2*x].sum+t[2*x+1].sum;
//}
//int main()
//{
//
//    return 0;
//}
#include <bits/stdc++.h>

using namespace std;
#define maxn 100007  //元素总个数
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
int Sum[maxn<<2],Add[maxn<<2];//Sum求和,Add为懒惰标记
int A[maxn],n;//存原数组数据下标[1,n]
//PushUp函数更新节点信息 ,这里是求和
void PushUp(int rt){Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];}
//Build函数建树
void Build(int l,int r,int rt){ //l,r表示当前节点区间,rt表示当前节点编号
	if(l==r) {//若到达叶节点
		Sum[rt]=A[l];//储存数组值
		return;
	}
	int m=(l+r)>>1;
	//左右递归
	Build(l,m,rt<<1);
	Build(m+1,r,rt<<1|1);
	//更新信息
	PushUp(rt);
}

void PushDown(int rt,int ln,int rn){
	//ln,rn为左子树,右子树的数字数量。
	if(Add[rt]){
        cout << rt <<endl;
		//下推标记
		Add[rt<<1]+=Add[rt];
		Add[rt<<1|1]+=Add[rt];
		//修改子节点的Sum使之与对应的Add相对应
		Sum[rt<<1]+=Add[rt]*ln;
		Sum[rt<<1|1]+=Add[rt]*rn;
		//清除本节点标记
		Add[rt]=0;
	}
}
void Update(int L,int C,int l,int r,int rt){//l,r表示当前节点区间,rt表示当前节点编号
	if(l==r){//到叶节点,修改
		Sum[rt]+=C;
		return;
	}
	int m=(l+r)>>1;
	//根据条件判断往左子树调用还是往右
	if(L <= m) Update(L,C,l,m,rt<<1);
	else       Update(L,C,m+1,r,rt<<1|1);
	PushUp(rt);//子节点更新了,所以本节点也需要更新信息
}
void Update(int L,int R,int C,int l,int r,int rt){//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号
    cout << l <<' '<<r <<endl;
	if(L <= l && r <= R){//如果本区间完全在操作区间[L,R]以内
		Sum[rt]+=C*(r-l+1);//更新数字和,向上保持正确
		Add[rt]+=C;//增加Add标记,表示本区间的Sum正确,子区间的Sum仍需要根据Add的值来调整
		return ;
	}
	int m=(l+r)>>1;

	PushDown(rt,m-l+1,r-m);//下推标记
	//这里判断左右子树跟[L,R]有无交集,有交集才递归
	if(L <= m) Update(L,R,C,l,m,rt<<1);
	if(R >  m) Update(L,R,C,m+1,r,rt<<1|1);
	PushUp(rt);//更新本节点信息
}
int Query(int L,int R,int l,int r,int rt){//L,R表示操作区间,l,r表示当前节点区间,rt表示当前节点编号

	if(L <= l && r <= R){
		//在区间内,直接返回
		return Sum[rt];
	}
	int m=(l+r)>>1;
	//下推标记,否则Sum可能不正确
	PushDown(rt,m-l+1,r-m);

	//累计答案
	int ANS=0;
	if(L <= m) ANS+=Query(L,R,l,m,rt<<1);
	if(R >  m) ANS+=Query(L,R,m+1,r,rt<<1|1);
	return ANS;
}
int main()
{
    cin >> n;
    for(int i =1;i <=n;i++)
        cin >> A[i];
	//建树
	Build(1,n,1);
	int ANS=Query(1,n,1,n,1);
	cout << ANS <<endl;
	//点修改
//	Update(L,C,1,n,1);
	//区间修改
	Update(1,5,1,1,n,1);
	//区间查询
	ANS=Query(1,n,1,n,1);
	cout << ANS<<endl;
    return 0;
}

字符串哈希

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5+5;
const int X=131;
ull pre[maxn],suf[maxn],p[maxn];
char s[maxn];
int n;
void Hash()
{
    p[0]=1;
    for(int i =1;i<=n;i++)
    {
        pre[i]=pre[i-1]*X+s[i]-'a'+1;
        p[i]=p[i-1]*X;
    }
    for(int i = n;i>=1;i--)
    {
        suf[i]=suf[i+1]*X+s[i]-'a'+1;
    }
}
ull getpre(int l,int r)
{
    return pre[r]-pre[l-1]*p[r-l+1];
}
ull getsuf(int l,int r)
{
    return suf[l]-suf[r+1]*p[r-l+1];
}
bool eql(int l1,int r1,int l2,int r2)
{
    return getpre(l1,r1)==getpre(l2,r2);
}
bool huiwen(int r)
{
    return getpre(1,r/2)==getsuf(ceil(r*1.0/2)+1,r);
}
bool check(int r)
{
    if(r&1)
    {
        return huiwen((r+1)/2)&&eql(1,(r+1)/2,(r+1)/2,r);
    }
        return huiwen(r/2)&&eql(1,r/2,r/2+1,r);
}
int main()
{
    cin >> s+1;
    n=strlen(s+1);
    Hash();
    int ans=0;
    for(int i = 1;i <= n;i++)
    {
        if(check(i))ans++;
    }
    printf("%d\n",ans);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值