zoukankan      html  css  js  c++  java
  • 模板整理(二)

    13.树状数组

    #include<cstdio>
    #include<cstring>
    #define lowerBit(x) (x&(-x))
    int num[10000];
    int n;
    void UpDate(int x,int y)//把第x个数加y
    {
    	while (x <= n)
    	{
    		num[x] += y;
    		x = x+lowerBit(x);
    	}
    }
    int Query(int x)//求从1到x的和 
    {
    	int sum = 0;
    	while (x > 0)
    	{
    		sum += num[x];
    		x = x-lowerBit(x);//x&(x-1)
    	}
    	   return sum;
    }
    int main()
    {
    	scanf ("%d",&n);
    	memset(num,0,sizeof(num));
    	for (int i = 1 ; i <= n ; i++)
    	{
    		int t;
    		scanf ("%d",&t);
    		UpDate(i,t);
    	}
    	
    	int m;
    	scanf ("%d",&m);
    	while (m--)
    	{
    		int x,y;
    		scanf ("%d %d",&x,&y);//看不懂
    		printf ("%d
    ",Query(y)-Query(x-1));
    	}
    	   return 0;
    }
    

      

     

    14.线段树//看不懂

     

    struct Node//不要左右子节点指针的做法 
    {
    	int L,R;
    	int minV,maxV;
    	int Mid()
    	{
    		return (L+R)/2;//还有这操作
    	}
    };
    Node tree[800010];//4倍叶子节点数量就够 
    
    
    void BuildTree(int root, int L, int R)
    {
    	tree[root].L = L;
    	tree[root].R = R;
    	tree[root].minV = INF;//这是为什么?到底哪个是大的
    	
    	 
    	
    	tree[root].maxV = -INF;//那个是小的?
    	if(L!=R)
    	{
    		BuildTree(2*root+1, L, (L+R)/2);
    		BuildTree(2*root+2, (L+R)/2+1, R);
    	}
    }
    
    
    void Insert(int root, int i, int v)
    //将第i个数,其值为v,插入线段树 
    {
    	if(tree[root].L == tree[root].R)//成立则亦有tree[root].R==i 
    	{
    		tree[root].minV = tree[root].maxV = v;
    		return ;
    	}
    	
    	tree[root].minV = min(tree[root].minV , v);
    	tree[root].maxV = max(tree[root].maxV , v);
    	if(i <= tree[root].Mid())
    	Insert(2*root + 1, i, v);
    	else
    	Insert(2*root + 2, i, v);
    }
    
    
    void Query(int root, int s, int e)
    //查询区间[s,e]中的最大值和最小值,如果更优就记录在全局变量里 
    {
    	if( tree[root].minV >= minV && tree[root].maxV <= maxV )
    		return;
    	if( tree[root].L == s && tree[root].R == e )
    	{
    		minV = min( minV, tree[root].minV );
    		//minV = min( minV, tree[root].minV );
    		maxV = max( maxV, tree[root].maxV );
    		return ;
    	}
    	if( e <= tree[root].Mid() )
    		Query( 2*root + 1, s, e );
    	else if( s > tree[root].Mid() )
    		Query( 2*root + 2, s, e );
    	else
    	{
    		Query( 2*root + 1, s, tree[root].Mid() );
    		Query( 2*root + 2, tree[root].Mid() + 1, e );
    		
    	}
    
    }
    

      

    15.KMP

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    //S: a b a b b a b a b a d a b a b a a a b a b a a
    //                                               j
    //                      T: a b a b a a a b a b a a
    //                  next :-1 0 0 1 2 3 1 1 2 3 4 5
    char s[1000], t[1000];
    int next[1000] = {-1, 0, 0, 1, 2, 3, 1, 1, 2, 3, 4, 5};
    int Kmp(char* s, int n, char* t, int m) {
        int i = 0, j = 0;
        while(i < n) {
            if(j == -1 || s[i] == t[j]) {
                ++i; ++j;
                if(j == m) {
                    return i - m + 1;
                }
            }
            else {
                j = next[j];
            }
        }
        return -1;
    }
    
    
    int main()
    {
        //ababababadababaaababaa
        //ababaaababaa
        //ababcabcacbab
        //abc
        scanf("%s%s", s, t);
        int l1 = strlen(s);
        int l2 = strlen(t);
        printf("第一个匹配的位置%d
    ", Kmp(s, l1, t, l2));
        return 0;
    }
    
    
    //next[i]: 0 -> i-1 最大的前缀和后缀匹配的长度 0 -> n-1
    //S: a b a b b a b a b a d a b a b a a a b a b a a
    //T: a b a b a a a b a b a a
    //  -1 0 0 1 2 3 1 1 2 3 4 5
    //从头选择next[j]个字符和从尾向前选择next[j]个字符是相等的
    //
    //1>, S串和T串前面这些字符是相等的
    //2>, T串前面字符有next[j]前缀和后缀匹配的长度
    

      

     

    16.二分图

     

    这个算法的主要思想还是“递归”,通过递归腾出位置来让更多的人匹配,以达到匹配人数最大化
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int f[500+5];		//女和哪个男配对 
    bool fr[505][505];		//可用vector<int> d[505]代替 
    bool vis[505];		//标记数组,表示这个人搜索过 
    int k,n,m;
    
    bool find(int x)		//寻找x男生,返回:能否找到人去匹配 
    {
    	for (int i = 1 ; i <= m ; i++)
    	{
    		if (fr[x][i] && !vis[i])
    		{
    			vis[i] = true;		//首先标记
    			if (f[i] == -1)		//如果该女生没有和别人匹配 
    			{
    				f[i] = x;		//则和该男生匹配 
    				return true;		//表示匹配完成 
    			}
    			else if (find(f[i]))		//如果该女生匹配的男生可以找到其他的女生匹配
    			{
    				f[i] = x;//递归的思想
    				return true;
    			}
    		}
    	}
    	return false;
    }
    
    int main()
    {
    	while (~scanf ("%d",&k) && k)
    	{
    		scanf ("%d %d",&n,&m);
    		memset(f,-1,sizeof(f));		//初始化,表示没有和任何人配对
    		memset(fr,false,sizeof(fr));		//初始化 
    		for (int i = 1 ; i <= k ; i++)
    		{
    			int x,y;
    			scanf ("%d %d",&x,&y);
    			fr[x][y] = true;
    		}
    		
    		int ans = 0;		//表示已经配对的男生数 
    		for (int i = 1 ; i <= n ; i++)
    		{
    			memset(vis,false,sizeof(vis));
    			if (find(i))
    				ans++;
    		}
    		printf ("%d
    ",ans);
    	}
    	return 0;
    }

    17.字典树模板

     1 #include<cstdio>
     2 #include<cstring>
     3 #define idx(x) (x-'a')
     4 struct Node
     5 {
     6     int v;
     7     Node *next[26];        //指向某个节点,作为其子节点之一 
     8     void init()
     9     {
    10         v = 0;        //当前节点有多少人公用
    11         for (int i = 0 ; i < 26 ; i++)
    12             next[i] = NULL; 
    13     }
    14 }Trie[100000];        //事先把内存分配好了 
    15 int ant;        //下一个节点要保存到的位置 
    16 void insert(char str[])
    17 {
    18     Node *p = &Trie[0];        //现在执行到的节点 
    19     int l = strlen(str);
    20     for (int i = 0 ; i < l ; i++)
    21     {
    22         if (p->next[idx(str[i])] == NULL)
    23         {
    24             p->next[idx(str[i])] = &Trie[ant];
    25             ant++;
    26             Trie[ant].init();            //随手初始化下一个节点 
    27             Trie[ant-1].v = 1;
    28             p = &Trie[ant-1];
    29         }
    30         else
    31         {
    32             p->v++;
    33             p = p->next[idx(str[i])];
    34         }
    35     }
    36 }
    37 
    38 int Query(char str[])        //char *str
    39 {
    40     int length = 0;
    41     Node p = Trie[0];
    42     int l = strlen(str);
    43     for (int i = 0 ; i < l ; i++)
    44     {
    45         if (p.next[idx(str[i])] == NULL)        //到此节点没有公共前缀的串了
    46         {
    47             break;
    48         }
    49         else
    50         {
    51             length++;
    52             p = *p.next[idx(str[i])];
    53         }
    54     }
    55     return length;
    56 }
    57 
    58 int main()
    59 {
    60     int n,m;
    61     char str[20];
    62     while (~scanf ("%d %d",&n,&m))
    63     {
    64         ant = 1;
    65         Trie[ant].init();
    66         for (int i = 1 ; i <= n ; i++)
    67         {
    68             scanf ("%s",str);
    69             insert(str);        //建树 
    70         }
    71         for (int i = 1 ; i <= m ; i++)
    72         {
    73             scanf ("%s",str);        //m次查询,查str的最长公共前缀
    74             printf ("%d
    ",Query(str));
    75         }
    76     }
    77     return 0;
    78 }
    79 /*
    80 3 5
    81 abac
    82 abcd
    83 accc
    84 
    85 a
    86 ab
    87 abe
    88 bc
    89 aca
    90 
    91 
    92 */
    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    linux包之coreutils之du和df命令
    java实现第六届蓝桥杯加法变乘法
    java实现第六届蓝桥杯奇妙的数字
    java实现第六届蓝桥杯奇妙的数字
    java实现第六届蓝桥杯打印大X
    java实现第六届蓝桥杯移动距离
    java实现第六届蓝桥杯移动距离
    java实现第六届蓝桥杯循环节长度
    java实现第六届蓝桥杯奇妙的数字
    java实现第六届蓝桥杯格子中输出
  • 原文地址:https://www.cnblogs.com/h-hkai/p/7410385.html
Copyright © 2011-2022 走看看