模板

java提交注意package
#pragma comment(linker, "/STACK:1024000000,1024000000")
kmp
void Next(int n){
    int j=0,k=-1;
    next[0]=-1;
    while(j<n){
        if(k==-1||org[j]==org[k]){
            j++;k++;
            if(org[j]!=org[k])next[j]=k;
            else next[j]=next[k];
        }
        else k=next[k];
    }
    return;
}
int search(int N,int n){//a为主串,b为模式串
    int i=0,j=0;
    while(i<N&&j<n){
        if(j==-1||a[i]==b[j]){i++;j++;}
        else j=next[j];
    }
    if(j>=n)return i-n;
    else return -1;
}

快速读入
/* 可以负数,不能小数*/
inline void inp( int &n ){
	n=0;
	int ch=getchar_unlocked(),sign=1;
	while( ch < '0' || ch > '9' ){if(ch=='-')sign=-1; ch=getchar_unlocked();}
	while( ch >= '0' && ch <= '9' )
 		n=(n<<3)+(n<<1)+ ch-'0', ch=getchar_unlocked();
	n=n*sign;
}
树状数组
二维树状数组
/*
    二维树状数组,low求低位,update向后更新,query查询
    update(x,y,num):x、y横纵坐标,num加数
    query(x,y):x,y横纵坐标,返回从1,1到x,y和,int范围
*/
inline int low(int x){
    return x&-x;
}
void update(int x,int y,int num){
    int Y=y;
    while(x<=n){
        y=Y;
        while(y<=n){
            sum[x][y]+=num;
            y+=low(y);
        }
        x+=low(x);
    }
}
int query(int x,int y){
    int Y=y,ans=0;
    while(x>0){
        y=Y;
        while(y>0){
            ans+=sum[x][y];
            y-=low(y);
        }
        x-=low(x);
    }
    return ans;
}
线段树
/*矩形周长,线段树*/

#define maxn 5005
#define lson l,m,rt<<1
#define rson m,r,rt<<1|1
struct Node{
    int num,len,lnum,lazy; //num为此线段覆盖次数,len为覆盖长度,lnum为段数,lazy为延迟数
    bool lc,rc; //表示线段两端有无被覆盖
};
struct Line{
    int l,r,y;
    bool up;
};
Line line[maxn<<1];
Node node[maxn<<2];
int num,x[maxn<<1];
void pushup(int rt){//向上更新
    node[rt].len=node[rt<<1].len+node[rt<<1|1].len;
    node[rt].lnum=node[rt<<1].lnum+node[rt<<1|1].lnum;
    node[rt].lc=node[rt<<1].lc;
    node[rt].rc=node[rt<<1|1].rc;
    node[rt].num=max(node[rt<<1].num,node[rt<<1|1].num);
    if(node[rt<<1].rc&&node[rt<<1|1].lc) node[rt].lnum--;//如果左孩子的右节点和右孩子的左节点都被标记,则线段数减1
    return;
}
void pushdown(int rt,int l,int r){//向下更新
    if(node[rt].lazy){
        int m=l+r>>1;
        node[rt<<1].len=x[m-1]-x[l-1];
        node[rt<<1|1].len=x[r-1]-x[m-1];
        node[rt<<1].num+=node[rt].lazy;
        node[rt<<1|1].num+=node[rt].lazy;
        node[rt<<1].lazy+=node[rt].lazy;
        node[rt<<1|1].lazy+=node[rt].lazy;
        if(node[rt<<1].num>0) 
node[rt<<1].lnum=node[rt<<1].lc=node[rt<<1].rc=1;
        else 
node[rt<<1].num=node[rt<<1].len=node[rt<<1].lnum=node[rt<<1].lc=node[rt<<1].rc=0; //如果覆盖数为0,则删除
        if(node[rt<<1|1].num>0) node[rt<<1|1].lnum=node[rt<<1|1].lc=node[rt<<1|1].rc=1;
        else node[rt<<1|1].num=node[rt<<1|1].len=node[rt<<1|1].lnum=node[rt<<1|1].lc=node[rt<<1|1].rc=0;
    }
    node[rt].lazy=0;
}
void add(int L,int R,int l,int r,int rt){//增加线段
    if(L<=l&&R>=r){
        node[rt].len=x[r-1]-x[l-1];
        node[rt].num++;
        node[rt].lc=node[rt].rc=node[rt].lnum=1;
        node[rt].lazy++;//延迟更新
        return;
    }
    pushdown(rt,l,r);
    int m=(l+r)>>1;
    if(L<m)add(L,R,lson);
    if(R>m)add(L,R,rson);
    pushup(rt);
    return;
}
void del(int L,int R,int l,int r,int rt){//删除线段
    if(L<=l&&R>=r){
        node[rt].num--;
        if(node[rt].num<=0){
            node[rt].len=0;
            node[rt].lc=node[rt].rc=node[rt].lnum=0;
            node[rt].num=0;
            node[rt].lazy--;//如果此线段被删除,延迟更新子线段
            return;
        }
        if(r-l==1)return;
    }
    pushdown(rt,l,r);
    int m=(l+r)>>1;
    if(L<m)del(L,R,lson);
    if(R>m)del(L,R,rson);
    pushup(rt);
    return;
}
bool cmp(Line a,Line b){
    if(a.y==b.y) return a.l<b.l;
    else return a.y<b.y;
}
inline int find(int key){//查询x坐标对应的下标,因为线段树要求从1开始,所以下标加1
    return lower_bound(x,x+num,key)-x+1;
}
int main()
{
    int n,i,x1,x2,y1,y2;
    scanf("%d",&n);
    num=0;
    for(i=0;i<n;i++){
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        x[num++]=x1;x[num++]=x2;
        line[i<<1].l=x1;line[i<<1].r=x2;line[i<<1].y=y1;line[i<<1].up=1;
        line[i<<1|1].l=x1;line[i<<1|1].r=x2;line[i<<1|1].y=y2;line[i<<1|1].up=0;
    }
    sort(x,x+num);//对x排序,离散化处理
    num=unique(x,x+num)-x;//去重
    n=n<<1;
    sort(line,line+n,cmp);
    int pre=0,ans=0;
    for(i=0;i<n-1;i++){
        if(line[i].up)//如果是下边,则加边
            add(find(line[i].l),find(line[i].r),1,num,1);
        else //如果是上边,则删除
            del(find(line[i].l),find(line[i].r),1,num,1);
        ans+=node[1].lnum*(line[i+1].y-line[i].y)*2;//平行y轴
        ans+=abs(node[1].len-pre);//平行x轴
        pre=node[1].len;
    }
    del(find(line[i].l),find(line[i].r),1,num,1);
    ans+=abs(node[1].len-pre);
    printf("%d\n",ans);
}
无向图重联通分量
/** 无向图重联通分量 Tarjan n^2*/
stack<int> S;
void dfs(int v,int f){
    vis[v]=1;
    dph[v]=low[v]=d++;
    S.push(v);
    for(int i=0; i<org[v].size(); i++){
        int u=org[v][i];
        if(u==f)continue;
        if(vis[u]==1)low[v]=min(low[v],dph[u]);
        else if(!vis[u]){
            dfs(u,v);
            low[v]=min(low[v],low[u]);
            if(low[u]>=dph[v]){//u为关节点
                num++;
                belong[v].pb(num);belong[u].pb(num);
                while(S.top()!=u){// 注意边界,如果吧push放在for循环里就是!=v不用pop,否则就是!=u最后还要pop
                    belong[S.top()].pb(num);
                    S.pop();
                }
                S.pop();
            }
        }
    }
    vis[v]=2;
}
int Tarjan() //搜索重联通分量
{
    num=0;
    while(!S.empty())S.pop();
    for(int i=1; i<=n; i++){
        d=0;
        if(!vis[i])
            dfs(i,-1);
    }
}
最大流 
Dinic
/*Dinic n^2*m 当前弧+GAP*/
#define INF 999999999
#define maxm 900000
#define maxn 1000
int n,s,t,flow;
struct edge{
    int v,c,f,next;
}e[maxm];
int first[maxn],cnt,cur[maxn],d[maxn],S,E;//S起点E终点
bool vis[maxn];
queue<int> q;
inline void addedge( int u, int v, int w ){
    e[cnt].v = v; e[cnt].c = w; e[cnt].f = 0;e[cnt].next = first[u]; first[u] = cnt++;
    e[cnt].v = u; e[cnt].c = 0; e[cnt].f = 0;e[cnt].next = first[v]; first[v] = cnt++;
}
int BFS()
{
    int u,v;
    while ( !q.empty())q.pop();
    q.push(S);
    memset(vis,0,sizeof(vis));
    d[s] = 0;  vis[s] = 1;
    while ( !q.empty() ) {
        u = q.front(); q.pop();
        for ( int i = first[u]; ~i; i = e[i].next ) {
            v = e[i].v;
            if ( !vis[v] && e[i].c > e[i].f ) {
                vis[v] = 1;
                q.push(v);
                d[v] = d[u] + 1;
            }
        }
    }
    return vis[t];
}
int DFS( int u, int a )
{
    if ( u == E || a == 0 ) return a;
    int fl = a,v,f;
    for ( int &i = cur[u]; ~i ; i = e[i].next ){ //i为cur[u]引用,当前弧优化
        v = e[i].v;
        if ( d[u] + 1 == d[v] && ( f = DFS( v, min( a, e[i].c - e[i].f ) ) ) > 0 ) {
            e[i].f += f;  e[i^1].f -= f;
            fl -= f;
            if ( !fl ) return a;
        }
    }
    return a-fl;
}
int dinic(int s,int e)
{
    S=s;E=e;
    int flow=0;
    while ( BFS() ){
        for ( int i = 1; i <= n; ++i )
           cur[i] = first[i];
        flow += DFS(s,INF);
    }
    return flow;
}
HLPP
/*HLPP n^2*m^0.5 有GAP优化*/
#define Maxn 205
#define Maxm 160005
int first[Maxn],d[Maxn],cnt,re[Maxn];
int num[Maxn];//判断断层
int KN;//汇点可以到达的最大标号
bool vis[Maxn];
int S,E;
queue<int> q;
struct node {
    int ind;
    bool operator<(const node &a) const {
        return d[ind]<d[a.ind];
    }
    node(int &x):ind(x) {}
};
priority_queue<node> order; //HL优化效果不明显
struct edge {
    int v,c,f,next;
} e[Maxm];
inline void add(int &a,int &b,int c){
    e[cnt].v=b; e[cnt].c=c; e[cnt].f=0; e[cnt].next=first[a]; first[a]=cnt++;
    e[cnt].v=a; e[cnt].c=0; e[cnt].f=0; e[cnt].next=first[b]; first[b]=cnt++;
}
void init() {
    while(!q.empty())q.pop();
    while(!order.empty())order.pop();
    memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num));
    KN=E; vis[E]=vis[S]=1; d[E]=0; d[S]=E; q.push(E);
    int i,u,v;
    while(!q.empty()) {
        u=q.front();
        q.pop();
        for(i=first[u]; ~i; i=e[i].next) {
            v=e[i].v;
            if(!vis[v]) {
                d[v]=d[u]+1; num[d[v]]++; vis[v]=1;
                q.push(v);
            }
        }
    }
    memset(re,0,sizeof(re));memset(vis,0,sizeof(vis));
    vis[S]=vis[E]=1;
    for(i=first[S]; ~i; i=e[i].next){
        v=e[i].v; re[v]+=e[i].c; e[i].f=e[i].c; e[i^1].f=-e[i].c;
        if(!vis[v]) order.push(v);
        vis[v]=1;
    }
}
int deal(){
    int u,v,Min,t,ii,f,i;
    while(!order.empty()) {
        u=order.top().ind; order.pop();
        if(d[u]>KN)continue; //不关心可行流,只关心结果,因此不用退回
        vis[u]=0;
        while(re[u]>0) {
            Min=1E9;
            for(i=first[u]; ~i; i=e[i].next){
                if(e[i].c==e[i].f)continue;
                t=e[i].v;
                if(d[t]+1==d[u]){
                    v=t;ii=i;break;
                }
                else if(Min>d[t])
                    v=t,ii=i,Min=d[t];
            }
            if(i==-1){
                if(--num[d[u]]==0) KN=min(KN,d[u]-1); //出现断层,更新最大标号
                d[u]=Min+1;
            }
            f=min(re[u],e[ii].c-e[ii].f);
            re[u]-=f; re[v]+=f; e[ii].f+=f; e[ii^1].f-=f;
            if(!vis[v])order.push(v);
            vis[v]=1;
        }
    }
    return re[E];
}
int HLPP(int s,int e){
    S=s;E=e;
    init();
    return deal();
}
最小费用流
(Primal-Dual)
/*最小费用流 (Primal-Dual) */
struct edge{
    int cost, cap, v, next;
}e[MAXM];
int first[MAXN], cnt;
int vis[MAXN], d[MAXN];
int ans, cost, src, des, n;
void init(){
    memset(first, -1, sizeof(first));
    cnt=ans=cost=0;
}
void add(int u, int v, int cap, int cost){
    e[cnt].v = v; e[cnt].cap = cap; e[cnt].cost =  cost; e[cnt].next = first[u]; first[u] = cnt++;
    e[cnt].v = u; e[cnt].cap =   0; e[cnt].cost = -cost; e[cnt].next = first[v]; first[v] = cnt++;
}
int aug(int u, int f){
    if(u == des){
        ans += cost * f;
        return f;
    }
    vis[u] = 1;
    int flow=f,t;
    for(int i = first[u]; ~i; i = e[i].next)
        if(e[i].cap && !e[i].cost && !vis[e[i].v]){
            t = aug(edge[i].v, min(tmp,edge[i].cap));
            edge[i].cap -= t; edge[i^1].cap += t;
            flow -= t;
            if(!flow) return f;
        }
    return f-flow;
}
deque<int>Q;
bool modlabel(){ //SPFA 增广
    for(int i = 0; i <= n; i++) d[i] = INF;
    d[des] = 0;
    whlie(!Q.empty())Q.pop();
    Q.push_back(des);
    while(!Q.empty()){
        int u = Q.front(), tmp;
        Q.pop_front();
        for(int i = first[u]; ~i ; i = e[i].next)
            if(e[i^1].cap && (tmp = d[u] - e[i].cost) < d[e[i].v])
                (d[e[i].v] = tmp) <= d[Q.empty() ? src : Q.front()] ? Q.push_front(e[i].v) : Q.push_back(e[i].v);
    }
    for(int u = 1; u <= n; u++)
        for(int i = first[u]; i != -1; i = e[i].next)
            e[i].cost += d[e[i].v] - d[u];
    cost += d[src];
    return d[src] < INF;
}
void costflow(){
    while(modlabel()){
        do memset(vis, 0, sizeof(vis));
        while(aug(src, INF));
    }
}
Zwk 适合最终流量大 费用范围不大 或增广路短的图  非负权值
/*zwk KM重标号 增广路同上,sap 不能用于负权值路*/
bool modlabel(){
    int delta = INF;
    for(int u = 1; u <= n; u++) if(vis[u])
            for(int i = first[u]; ~i ; i = e[i].next)
                if(e[i].cap && !vis[e[i].v] && e[i].cost < delta) delta = e[i].cost;
    if(delta == INF) return false;
    for(int u = 1; u <= n; u++) if(vis[u])
            for(int i = first[u]; ~i ; i = e[i].next)
                edge[i].cost -= delta, edge[i^1].cost += delta;
    cost += delta;
    return true;
}
void costflow()
{
    do{
        do memset(vis, 0, sizeof(vis));
        while(aug(src, INF));
    }while(modlabel());
}

最短路
SPFA
/**
    复杂度分析:
        普通SPFA km kmax=n 不适合稠密图 一般为2
        优先级队列  加入节点复杂度logn 节点数太多时适得其反,对于特殊数据速度略小于普通spfa
                     对于随机图效果很好
        手动模拟SLF,LLL 复杂度低于优先级队列,最坏情况与普通SPFA持平

*/

#define Maxn 100010//最大点数
#define Maxm 400010//最大边数,无向图要建双向边
int w[Maxm],u[Maxm],next[Maxm],cnt;
int first[Maxn],havein[Maxn];//havin为入队次数
long long d[Maxn];//距离
int n;
bool in[Maxn];//队中标志
inline void add(int vn,int un,int wn){//邻接表存储
    u[cnt]=un;w[cnt]=wn;next[cnt]=first[vn];first[vn]=cnt++;
}
struct node{
    int v,dd;
    node(int &a):v(a),dd(d[a]){};
    bool operator< (const node& a)const{
        return dd>a.dd;
    }
};
priority_queue<node> q; //利用优先级队列SLF和LLL
bool spfa(int s){
    int i,now,ne,t;
    memset(in,0,sizeof(in));
    memset(havein,0,sizeof(havein));
    for(i=0;i<n;i++)d[i]=INF; //memset(d,0x3f,sizeof(d));
    d[s]=0;in[s]=1;q.push(s);
    while(!q.empty()){
        now=q.top().v;q.pop();
        if(!in[now])continue;
        in[now]=0;
        for(i=first[now];~i;i=next[i]){
            ne=u[i];
            if(d[ne]<=(t=d[now]+w[i]))continue;
            d[ne]=t; in[ne]=1; q.push(ne);
            if(++havein[ne]>n)return 0;//判断有无负环
        }
    }
    return 1;//返回1为正常,0为有负环
}
#define M 200000  //手动模拟
int q[M];
bool spfa(int s){
    int i,now,ne,t;
    memset(in,0,sizeof(in));
    memset(havein,0,sizeof(havein));
    memset(d,0x3f,sizeof(d));
    int l,r,len;l=r=len=0;
    long long sum=0;
    d[s]=0;in[s]=havein[s]=1;
    q[r++]=s;len++;
    while(l!=r){
        now=q[l++];
        if(l==M)l=0;
        if(d[now]*len>sum){//LLL
            q[r++]=now;
            if(r==M)r=0;
            continue;
        }
        len--; sum-=d[now]; in[now]=0;
        for(i=first[now];~i;i=Next[i]){
            ne=u[i];
            if(d[ne]<=(t=d[now]+w[i]))continue;
            d[ne]=t;
            if(in[ne])continue;
            in[ne]=1;
            if(t<=d[q[l]]){ //SLF
                if(--l<0)l=M-1;
                q[l]=ne;
            }
            else{
                q[r++]=ne;
                if(r==M)r=0;
            }
            len++; sum+=t;
            if(++havein[ne]>n)return 0;
        }
    }
    return 1;//返回1为正常,0为有负环
}
void init()//边初始化
{
    cnt=0;
    memset(first,-1,sizeof(first));
}
dijkstra
/*dijkstra 复杂度M+NlgN*/
struct node
{
    double dis;
    int v;
    node(int &a):v(a),dis(d[a]){}
    bool operator <(const node &b)const{
        if(dis==b.dis)return n>b.n;
        return dis>b.dis;//注意符号!!这是降序排列
    }
};
priority_queue<node> q;
void dijkstra(int s)
{
    while(!q.empty())q.pop();
    int i,x;
    memset(vis,0,sizeof(vis));
    memset(d,0x3f,sizeof(d));
    d[s]=0; q.push(s);
    while(!q.empty()){
        x=q.top().v;q.pop();
        if(now.dis!=dis[x]||vis[x])continue;
        vis[x]=1;
        for(i=1;i<=n;i++){
            if(!vis[i]&&dis[i]>dis[x]+map[x][i]){
               dis[i]=dis[x]+map[x][i];
               q.push(i);
            }
        }
    }
    return;
}
拓扑排序
/**拓扑排序 n^2 递归版 注意爆栈*/
int inq[Maxn];
int topo[Maxn],t;//topo为结果序列
bool dfs(int u){
    inq[u]=-1;//正在队列中
    for(int v=0;v<n;v++)
      if(G[u][v]){ //邻接矩阵
          if(inq[v]<0)return 0;//存在有向环
          else if(!inq[v]&&!dfs(v))return 0;
      }
    inq[u]=1;topo[--t]=u;
    return 1;
}
bool toposort(){
    t=n;
    memset(inq,0,sizeof(inq));
    for(int u=0;u<n;u++)
      if(!inq[u]&&!dfs(u))return 0;
    return 1;
}
/*循环版 需要统计入度*/
int in[Maxn];//节点入度
int st[Maxn],cnt;//记录入度为0的点栈
bool toposort(){
    for(int i=n,now; i>=1; i--){ //节点数
        if(cnt==0)return 0;//没有入度为0的节点
        now=st[--cnt];
        for(int nn=1; nn<=n; nn++)
            if(map[now][nn]&&(--in[nn])==0)st[cnt++]=nn;
        in[now]=i; ans[i]=now;
    }
    return 1;
}
最大匹配
/**
二分图最大匹配:Hopcroft-Karp算法
复杂度:N^0.5 * M
*/
//对于要匹配的点 分为x集合的点,和y集合的点
int Mx[MAX],My[MAX];//那么这里的Mx[i]的值表示x集合中i号点的匹配点,My[j]的值就是y集合j点匹配的点
int dx[MAX],dy[MAX];//这里就是bfs找增广路用的数组 对于u-->v可达就有dy[v] = dx[u] + 1
int vis[MAX],dis;//辅助
queue<int>Q;
bool bfs() //最短增广路
{
	int i ,v,u;
	dis = INF;
	while(!Q.empty())q.pop();
	memset(dx,-1,sizeof(dx));
	memset(dy,-1,sizeof(dy));
	for(i = 0; i < m ;i ++) // 寻找x中未匹配的
		if(Mx[i] == -1)  Q.push(i),dx[i] = 0;
	while(!Q.empty()){
		u = Q.front(); Q.pop();
		if(dx[u] > dis) break;
		for(i = head[u]; i != -1; i = edge[i].next){
			v = edge[i].to;
			if(dy[v] == -1){
				dy[v] = dx[u] + 1;
				if(My[v] == -1) dis = dy[v];
				else{
					dx[My[v]] = dy[v] + 1;
					Q.push(My[v]);
				}
			}
		}
	}
	return dis != INF;
}
bool dfs(int u){
	int v;
	for(int i = head[u]; i != -1; i = edge[i].next){
		v = edge[i].to;
		if(!vis[v] && dy[v] == dx[u] + 1){
			vis[v] = 1;
			if(My[v] != -1 && dy[v] == dis) continue;
			if(My[v] == -1 || dfs(My[v])){
				Mx[u] = v; My[v] = u;
				return true;
			}
		}
	}
	return false;
}
int match(){
	int ans = 0;
	memset(Mx,-1,sizeof(Mx));
	memset(My,-1,sizeof(My));
	while(bfs()){
		memset(vis,0,sizeof(vis));
		for(int u = 0; u < m; u ++)
			if(Mx[u] == -1 && dfs(u))//这里特别要注意,Mx[u] == -1 && dfs(u)先后顺序千万不能换,dfs之后Mx[u]就会变化
				ans ++;
	}
	return ans;
}

 

posted @ 2014-02-17 15:12  czjxy881  阅读(122)  评论(0编辑  收藏  举报