一些模板

string 操作:

 1 =,assign()   //赋以新值
 2 s.assign(str); 
 3 s.assign(str,1,3);//如果str是”iamangel” 就是把”ama”赋给字符串
 4 s.assign(str,2,string::npos);//把字符串str从索引值2开始到结尾赋给s
 5 s.assign(“gaint”); 
 6 s.assign(“nico”,5);//把’n’ ‘I’ ‘c’ ‘o’ ‘\0’赋给字符串
 7 s.assign(5,’x’);//把五个x赋给字符串
 8 b) swap()   //交换两个字符串的内容
 9 c) +=,append(),push_back() //在尾部添加字符
10 d) insert() //插入字符
11 e) erase() //删除字符
12 g) replace() //替换字符
13 h) +//串联字符串
14 ==,!=,<,<=,>,>=,compare()  //比较字符串
15 string s(“abcd”);
16     s.compare(“abcd”); //返回0
17     s.compare(“dcba”); //返回一个小于0的值
18     s.compare(“ab”); //返回大于0的值
19     s.compare(s); //相等
20     s.compare(0,2,s,2,2); //用”ab”和”cd”进行比较 小于零
21     s.compare(1,2,”bcx”,2); //用”bc”和”bc”比较。
22 j) size(),length()  //返回字符数量
23 r) copy() //将某值赋值为一个C_string
24 s) c_str() //将内容以C_string返回
25 u) substr() //返回某个子字符串
26     s.substr(11);//从索引11往后的子串
27     s.substr(5,6);//从索引5开始6个字符
28 k)find()
29 string::size_type position;  
30 position = s.find("xx");  
31 //查找s 中flag 出现的所有位置。  
32  flag="a";  
33 position=0;  
34 while((position=s.find_first_of(flag,position))!=string::npos)  
35 {  
36 //position=s.find_first_of(flag,position);  
37 cout<<"position  : "<<position<<endl;  
38 position++;  
39  }  

GCD :

int gcd(int x,int y){
    return y?gcd(y,x%y):x;
} 

LCM :

int lcm(int a,int b) {return a*b/gcd(a,b);  }

扩展欧几里得 :

 1 int exgcd(int a, int b, int& x, int& y){//a*x+b*y=gcd(a,b)=d;(x,y)为其一组整数解
 2     int d = a;
 3     if(b != 0){
 4         d = exgcd(b, a % b, y, x);
 5         y -= (a / b) * x;
 6     }else {
 7         x = 1;
 8         y = 0;
 9     }
10     return d;
11 }

快速幂 :

 1 ll quick_power(ll base, ll n){
 2     ll res = 1;
 3     while (n > 0){
 4         if (n & 1)
 5             res *= base; // res = (res * base) % mod;
 6         base *= base; //base = (base * base) % mod;
 7         n >>= 1;
 8     }
 9     return res;
10 }

矩阵快速幂 :

 1 int mod;
 2 int n,m,sum;
 3 struct mtix{
 4     int a[maxn][maxn];
 5     mtix(){memset(a,0,sizeof(a));}
 6 }f;
 7 mtix mul(mtix a,mtix b){
 8     mtix c;
 9     for (int i=1;i<=n;i++)
10         for (int j=1;j<=n;j++)
11             for (int k=1;k<=n;k++)
12             {c.a[i][j]+=(a.a[i][k]*b.a[k][j])%mod;c.a[i][j]%=mod;}
13     return c;
14 }
15 mtix mpow(int y){
16     mtix ans;
17     mtix tem=f;
18     for (int i=1;i<=n;i++)
19         ans.a[i][i]=1;
20     for (;y;tem=mul(tem,tem),y>>=1)
21         if (y&1) ans=mul(ans,tem);
22     for (int i=1;i<=n;i++)
23         sum+=ans.a[i][i];
24     cout<<sum%mod<<endl;
25     return ans;
26 }
27 int main(){
28     cin>>n>>m;
29     for (int i=1;i<=n;i++)
30         for (int k=1;k<=n;k++)
31             cin>>f.a[i][k];
32     mpow(m);
33 }

最长公共子序列LCS :

 1 char a[1010],b[1010];
 2 int dp[1010][1010];
 3 int main(){
 4     int lena,lenb,i,j;
 5     while(scanf("%s%s",&a,&b)!=EOF){
 6         lena=strlen(a);
 7         lenb=strlen(b);
 8         memset(dp,0,sizeof(dp));
 9         for(i=1;i<=lena;++i){
10             for(j=1;j<=lenb;++j){
11                 if(a[i-1]==b[j-1])
12                     dp[i][j]=dp[i-1][j-1]+1;
13                 else
14                     dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
15             }
16         }
17         printf("%d\n",dp[lena][lenb]);
18     }
19     return 0;
20 }

最短路Floyd :

1 for (int k = 1; k <= n; k++) {
2     for (int i = 1; i <= n; i++) {
3         if (i == k) continue;
4         for (int j = 1; j <= n; j++) {
5             if (i == j || k == j) continue;
6             dis[i][j] = min(dis[i][j], dis[i][k]+ dis[k][j]);
7         }
8     }
9 }

并查集 :

 1 int pre[maxn];
 2 int tot[maxn];//集合元素数量
 3 int Rank[maxn];//集合排名
 4 int n,m,k;
 5 void init(){
 6     for(int i=1;i<=n;++i){
 7         pre[i]=i;
 8         tot[i]=1;
 9     }
10     mst(Rank,0);
11 }
12 int find(int x){
13     if(x==pre[x])
14         return x;
15     else
16         return pre[x]=find(pre[x]);
17 }
18 
19 void join(int x, int y){
20     x = find(x);
21     y = find(y);
22     if (Rank[x] > Rank[y]){
23         pre[y] = x;
24         if (x != y)
25             tot[x] += tot[y];
26     }
27     else{
28         pre[x] = y;
29         if (x != y)
30             tot[y] += tot[x];
31         if (Rank[x] == Rank[y])
32             Rank[y] += 1;
33     }
34 }

SG 打表 :

//f[]:可以取走的石子个数
//sg[]:0~n的SG函数值
int f[maxn],sg[maxn],mex[maxn];
void getSG(int n){
    int i,j;
    memset(sg,0,sizeof(sg));
    for(i=1;i<=n;i++){
        memset(mex,0,sizeof(mex));
        for(j=1;f[j]<=i&&f[j]<=m;j++) //注意加f[i]的限定条件,此处为f[j]<=m
            mex[sg[i-f[j]]]=1;
        for(j=0;j<=n;j++){    //求mex中未出现的最小的非负整数
            if(mex[j]==0){
                sg[i]=j;
                break;
            }
        }
        //cout<<i<<" "<<sg[i]<<endl;
    }
}
 1 int f[maxn],sg[maxn];bool mex[maxn];
 2 void getsg(int k,int n){
 3     int i,j;
 4     memset(sg,0,sizeof(sg));
 5     for(i=1;i<=n;i++){
 6         memset(mex,0,sizeof(mex));
 7         for(j=1;f[j]<=i&&j<=k;j++)
 8             mex[sg[i-f[j]]]=true;
 9         for(j=0;j<=n;j++){
10             if(mex[j]==false){
11                 sg[i]=j;
12                 break;
13             }
14         }
15     }
16 }//这个好像更快

SG_DFS :

 1 1 //注意 S数组要按从小到大排序 SG函数要初始化为-1 对于每个集合只需初始化1遍
 2  2 //n是集合s的大小 S[i]是定义的特殊取法规则的数组
 3  3 int s[110],sg[10010],n;
 4  4 int SG_dfs(int x)
 5  5 {
 6  6     int i;
 7  7     if(sg[x]!=-1)
 8  8         return sg[x];
 9  9     bool mex[110];
10 10     memset(mex,0,sizeof(mex));
11 11     for(i=0;i<n;i++)
12 12     {
13 13         if(x>=s[i])
14 14         {
15 15             SG_dfs(x-s[i]);
16 16             mex[sg[x-s[i]]]=1;
17 17         }
18 18     }
19 19     int e;
20 20     for(i=0;;i++)
21 21         if(!mex[i])
22 22         {
23 23             e=i;
24 24             break;
25 25         }
26 26     return sg[x]=e;
27 27 }

线段树 :

 1 //求和为例建树 
 2 1 const int MAXM=50000;          //定义 MAXM 为线段最大长度
 3  2 
 4  3 int a[MAXM+5],st[(MAXM<<2)+5];    // a 数组为 main 函数中读入的内容,st 数组为需要查询的数的信息(如和、最值等),树的空间大小为线段最大长度的四倍
 5  4 
 6  5 void build(int o,int l,int r){    //传入的参数为 o:当前需要建立的结点;l:当前需要建立的左端点;r:当前需要建立的右端点
 7  6     if(l==r)st[o]=a[l];      //当左端点等于右端点即建立叶子结点时,直接给数组信息赋值
 8  7     else{
 9  8         int m=l+((r-l)>>1);      // m 为中间点,左儿子结点为 [l,m] ,右儿子结点为 [m+1,r];
10  9         build(o<<1,l,m);        //构建左儿子结点
11 10         build((o<<1)|1,m+1,r);     //构建右儿子结点
12 11         st[o]=st[o<<1]+st[(o<<1)|1];  //递归返回时用儿子结点更新父节点,此处可进行更新最大值、最小值、区间和等操作
13 12     }
14 13 }
15 14 
16 15 {                       //在 main 函数中的语句
17 16         build(1,1,n);
18 17 }
 1 //单点修改
 2 void update(int o,int l,int r,int ind,int ans){  //o、l、r为当前更新到的结点、左右端点,ind为需要修改的叶子结点左端点,ans为需要修改成的值;
 3     if(l==r){                      //若当前更新点的左右端点相等即到叶子结点时,直接更新信息并返回
 4         st[o]=ans;
 5         return;
 6     }
 7     int m=l+((r-l)>>1);
 8     if(ind<=m){                      //若需要更新的叶子结点在当前结点的左儿子结点的范围内,则递归更新左儿子结点,否则更新右儿子结点
 9         update(o<<1,l,m,ind,ans);
10     }
11     else{
12         update((o<<1)|1,m+1,r,ind,ans);
13     }
14     st[o]=max(st[o<<1],st[(o<<1)|1]);//递归回之后用儿子结点更新父节点(此处是区间最大值)
15 }
16 
17 {                               //在main函数中的语句
18         update(1,1,n,ind,ans);
19 }
 1 //单点修改的区间查询
 2 int query(int o,int l,int r,int ql,int qr){      //ql、qr为需要查询的区间左右端点
 3     if(ql>r||qr<l) return -1;              //若当前结点和需要查找的区间不相交,则返回一个对于区间查询无关的值(如求和时返回0,求最大值时返回-1等)
 4     if(ql<=l&&qr>=r) return st[o];        //若当前结点的区间被需要查询的区间覆盖,则返回当前结点的信息
 5     int m=l+((r-l)>>1);
 6     int p1=query(o<<1,l,m,ql,qr),p2=query((o<<1)|1,m+1,r,ql,qr);  //p1为查询左儿子结点得到的信息,p2为查询右儿子结点得到的信息
 7     return max(p1,p2);    //综合两个儿子结点的信息并返回
 8 }
 9 
10 {    //main函数中的语句
11         printf("%d\n",query(1,1,n,a,b));
12 }

然后是线段数的区间修改以及相应的查询:

区间修改用到了lazy的思想,即当一个区间需要更新时,只递归更新到那一层结点,并将其下层结点所需要更新的信息保存在数组中,然后返回,只有当下次遍历到那个结点(更新过程中或查询过程中),才将那个结点的修改信息传递下去,这样就避免了区间修改的每个值的修改

区间修改(包括区间加值和区间赋值)及相应查询:

 1 //区间加值
 2 void pushup(int o){          //pushup函数,该函数本身是将当前结点用左右子节点的信息更新,此处求区间和,用于update中将结点信息传递完返回后更新父节点
 3     st[o]=st[o<<1]+st[o<<1|1];
 4 }
 5   
 6 void pushdown(int o,int l,int r){  //pushdown函数,将o结点的信息传递到左右子节点上
 7     if(add[o]){             //当父节点有更新信息时才向下传递信息
 8         add[o<<1]+=add[o];      //左右儿子结点均加上父节点的更新值
 9         add[o<<1|1]+=add[o];
10         int m=l+((r-l)>>1);
11         st[o<<1]+=add[o]*(m-l+1);  //左右儿子结点均按照需要加的值总和更新结点信息
12         st[o<<1|1]+=add[o]*(r-m);
13         add[o]=0;                //信息传递完之后就可以将父节点的更新信息删除
14     }
15 }
16  
17 void update(int o,int l,int r,int ql,int qr,int addv){  //ql、qr为需要更新的区间左右端点,addv为需要增加的值
18     if(ql<=l&&qr>=r){                      //与单点更新一样,当当前结点被需要更新的区间覆盖时
19         add[o]+=addv;                      //更新该结点的所需更新信息
20         st[o]+=addv*(r-l+1);                //更新该结点信息
21         return;                    //根据lazy思想,由于不需要遍历到下层结点,因此不需要继续向下更新,直接返回
22     }
23     
24     pushdown(o,l,r);                  //将当前结点的所需更新信息传递到下一层(其左右儿子结点)
25     int m=l+((r-l)>>1);
26     if(ql<=m)update(o<<1,l,m,ql,qr,addv);     //当需更新区间在当前结点的左儿子结点内,则更新左儿子结点
27     if(qr>=m+1)update(o<<1|1,m+1,r,ql,qr,addv);   //当需更新区间在当前结点的右儿子结点内,则更新右儿子结点
28     pushup(o);                  //递归回上层时一步一步更新回父节点
29 }
30 
31 ll query(int o,int l,int r,int ql,int qr){    //ql、qr为需要查询的区间
32     if(ql<=l&&qr>=r) return st[o];      //若当前结点覆盖区间即为需要查询的区间,则直接返回当前结点的信息
33     pushdown(o,l,r);                  //将当前结点的更新信息传递给其左右子节点
34     int m=l+((r-l)>>1);
35     ll ans=0;                      //所需查询的结果
36     if(ql<=m)ans+=query(o<<1,l,m,ql,qr);     //若所需查询的区间与当前结点的左子节点有交集,则结果加上查询其左子节点的结果
37     if(qr>=m+1)ans+=query(o<<1|1,m+1,r,ql,qr); //若所需查询的区间与当前结点的右子节点有交集,则结果加上查询其右子节点的结果
38    return ans; 
39 }
 1 //区间改值(其实只有pushdow函数和update中修改部分与区间加值不同)
 2 void pushup(int o){
 3      st[o]=st[o<<1]+st[o<<1|1];
 4  }
 5  
 6  void pushdown(int o,int l,int r){  //pushdown和区间加值不同,改值时修改结点信息只需要对修改后的信息求和即可,不用加上原信息
 7      if(change[o]){
 8          int c=change[o];
 9          change[o<<1]=c;
10          change[o<<1|1]=c;
11          int m=l+((r-l)>>1);
12          st[o<<1]=(m-l+1)*c;
13          st[o<<1|1]=(r-m)*c;
14          change[o]=0;
15      }
16  }
17  
18  void update(int o,int l,int r,int ql,int qr,int c){
19      if(ql<=l&&qr>=r){         //同样更新结点信息和区间加值不同
20          change[o]=c;
21          st[o]=(r-l+1)*c;
22          return;
23      }
24      
25      pushdown(o,l,r);
26      int m=l+((r-l)>>1);
27      if(ql<=m)update(o<<1,l,m,ql,qr,c);
28      if(qr>=m+1)update(o<<1|1,m+1,r,ql,qr,c);
29      pushup(o);
30  }
31  
32  int query(int o,int l,int r,int ql,int qr){
33      if(ql<=l&&qr>=r) return st[o];
34      pushdown(o,l,r);
35      int m=l+((r-l)>>1);
36      int ans=0;
37      if(ql<=m)ans+=query(o<<1,l,m,ql,qr);
38      if(qr>=m+1)ans+=query(o<<1|1,m+1,r,ql,qr);
39      return ans;
40  }

看到好的链接:https://blog.csdn.net/zxzxzx0119/article/details/79838261

acwing模板:https://www.acwing.com/activity/content/11/

posted @ 2019-08-07 21:28  acwarming  阅读(151)  评论(0编辑  收藏  举报