国赛死亡冲刺

二分

模板:

bool check(int x) {/* ... */} // 检查x是否满足某种性质

// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

浮点数二分算法模板

bool check(double x) {/* ... */} // 检查x是否满足某种性质

double bsearch_3(double l, double r)
{
    const double eps = 1e-6;   // eps 表示精度,取决于题目对精度的要求
    while (r - l > eps)
    {
        double mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid;
    }
    return l;
}

例题:
789. 数的范围
https://www.acwing.com/problem/content/791/

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5+5;
int n,q;
int a[N];
//不小于
int fun1(int x){
    int l=0;
    int r=n-1;
    while(l<r){
        int mid=(l+r)>>1;
        if(a[mid]<x){
            l=mid+1;
        }
        else r=mid;
    }
    if(a[l]!=x) return -1;
    else return l;
}
//不大于
int fun2(int x){
    int l=0;
    int r=n-1;
    while(l<r){
        int mid=(l+r+1)>>1;
        if(a[mid]>x) r=mid-1;
        else l=mid;
    }
    if(a[l]!=x) return -1;
    else return l;
}
int main()
{
    cin>>n>>q;
    for (int i = 0; i < n; i ++ ){
        cin>>a[i];
    }
    while(q--){
        int k;
        cin>>k;
        cout<<fun1(k)<<" "<<fun2(k)<<endl;
    }
    return 0;
}

前缀和与差分

前缀和

二维前缀和
796. 子矩阵的和
https://www.acwing.com/problem/content/798/

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e3+5;
int s[N][N];//s[i][j]该点左上角的矩阵前缀和
int n,m,q;
int get_prefix_sum(int x1,int y1,int x2,int y2){
    return s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
}
int main()
{   
    cin>>n>>m>>q;
    for (int i = 1; i <= n; i ++ ){
        for(int j = 1;j <= m;j ++){
            cin>>s[i][j];
            s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];
        }
    }
    while(q--){
        int x1,y1,x2,y2;
        cin>>x1>>y1>>x2>>y2;
        cout<<get_prefix_sum(x1,y1,x2,y2)<<endl;
    }
    return 0;
}

差分

  1. 差分
    https://www.acwing.com/problem/content/799/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int a[N];
int n,m;
void insert(int l,int r,int x){
    a[l]+=x;
    a[r+1]-=x;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        insert(i,i,x);
    }
    while(m--){
        int l,r,c;
        cin>>l>>r>>c;
        insert(l,r,c);
    }
    for(int i=1;i<=n;i++){
        a[i]+=a[i-1];
        cout<<a[i]<<" ";
    }
    puts("");
  return 0;
}
//  freopen("testdata.in", "r", stdin);

二维差分
798. 差分矩阵
https://www.acwing.com/problem/content/800/

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=1005;
int a[N][N];//前缀和是以左上角看 差分就以右下角看
int n,m,q;
void insert(int x1,int y1,int x2,int y2,int x){
    a[x1][y1]+=x;
    a[x2+1][y1]-=x;
    a[x1][y2+1]-=x;
    a[x2+1][y2+1]+=x;
}
int main(){
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int x;
            cin>>x;
            insert(i,j,i,j,x);
        }
    }
    while(q--){
        int x1,y1,x2,y2,c;
        cin>>x1>>y1>>x2>>y2>>c;
        insert(x1,y1,x2,y2,c);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
            cout<<a[i][j]<<" ";
        }
        puts("");
    }
  return 0;
}
//  freopen("testdata.in", "r", stdin);

并查集

  1. 合并集合
    https://www.acwing.com/problem/content/838/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int p[N];
int n,m;
int find(int x){
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) p[i]=i;
    while(m--){
        char c;
        int a,b;
        cin>>c>>a>>b;
        int x=find(a);
        int y=find(b);
        if(c=='M'){
            if(x!=y) p[x]=y;
        }
        else if(x==y) puts("Yes");
        else puts("No");
    }
  return 0;
}
//  freopen("testdata.in", "r", stdin);

trie

  1. Trie字符串统计
    https://www.acwing.com/problem/content/837/
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
const int N=1e5+5;
char c[N];
int son[N][26],cnt[N],idx;
char str[N];
void insert(char *str){
    int p=0;
    for(int i=0;str[i];i++){
        int u=str[i]-'a';
        if(!son[p][u]) son[p][u]=++idx;
        p=son[p][u];
    }
    cnt[p]++;//以该字符结尾计数
}
int query(char * str){
            int p=0;
    for(int i=0;str[i];i++){
        int u=str[i]-'a';
        if(!son[p][u]) return 0;
        p=son[p][u];
    }
    return cnt[p];
}
int main()
{
    int n;
    scanf("%d", &n);
    while (n -- )
    {
        char op[2];
        scanf("%s%s", op, str);
        if (*op == 'I') insert(str);
        else printf("%d\n", query(str));
    }

    return 0;
}
//  freopen("testdata.in", "r", stdin);

单调队列

  1. 滑动窗口
    https://www.acwing.com/problem/content/156/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=1e6+5;
int n,k;
int a[N],q1[N],q2[N];
void min_queue(){
    int hh=0,tt=-1;
    for(int i=0;i<n;i++){
        //判断队头是否已经弹出
        if(hh<=tt && i-k+1>q1[hh]) hh++;
        //删除所有比当前值小的数
        while(hh<=tt && a[i]<=a[q1[tt]]) tt--;
        q1[++tt]=i;
        if(i>=k-1) printf("%d ",a[q1[hh]]);
    }
    puts("");
}
void max_queue(){
    int hh=0,tt=-1;
    for(int i=0;i<n;i++){
        //判断队头是否已经弹出
        if(hh<=tt && i-k+1>q2[hh]) hh++;
        //删除所有比当前值小的数
        while(hh<=tt && a[i]>=a[q2[tt]]) tt--;
        q2[++tt]=i;
        if(i>=k-1) printf("%d ",a[q2[hh]]);
    }
    puts("");
}
int main(){
    cin>>n>>k;
    for(int i=0;i<n;i++) scanf("%d",a+i);
    min_queue();
    max_queue();
  return 0;
}
//  freopen("testdata.in", "r", stdin);

双指针

  1. 最长连续不重复子序列
    https://www.acwing.com/problem/content/801/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=1e5+5;
int a[N];
int st[N];
int n;
int main(){
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];
    int res=0;
    for(int i=0,j=0;i<n;i++){
        st[a[i]]++;
        while(st[a[i]]>1 && j<i){
            st[a[j]]--;
            j++;
        }
        res=max(res,i-j+1);
    }
    cout<<res<<endl;
  return 0;
}
//  freopen("testdata.in", "r", stdin);

图论

spfa

  1. spfa求最短路
    https://www.acwing.com/problem/content/853/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
typedef pair<int,int>PII;
const int N=1e6+5;
int h[N],e[N],w[N],ne[N],idx;
int dist[N];
bool st[N];//标记当前队列有哪些元素
int n,m;
void add(int a,int b,int c){
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;
}
void fun(){
    memset(dist,0x3f,sizeof dist);
    dist[1]=0;
    st[1]=true;
    queue<int >q;
    q.push(1);
    while(q.size()){
        int k=q.front();
        st[k]=false;
        q.pop();
        for(int i=h[k];i!=-1;i=ne[i]){
            int j=e[i];
            if(dist[j]>dist[k]+w[i]){
                dist[j]=dist[k]+w[i];
                if(!st[j]){//队列中没有j
                    q.push(j);
                    st[j]=true;
                }
            }
        }
    }
}
int main(){
    cin>>n>>m;
    memset(h,-1,sizeof h);
    while(m--){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
    }
    fun();
    if (dist[n] > 0x3f3f3f3f / 2) puts("impossible");
    else cout<<dist[n]<<endl;
  return 0;
}
//  freopen("testdata.in", "r", stdin);

最小生成树

  1. Kruskal算法求最小生成树
    https://www.acwing.com/problem/content/861/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=1e5+10,M=2e5+10,INF=0x3f3f3f3f;
int n,m;
int p[N];
struct Edge{
    int a,b,c;
}edge[M];
bool cmp(Edge x,Edge y){
    return x.c<y.c;
}
int find(int x){
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}
int kruskal(){
    for(int i=1;i<=n;i++) p[i]=i;
    int res=0,cnt=0;
    for(int i=1;i<=m;i++){
        int a=edge[i].a;
        int b=edge[i].b;
        int c=edge[i].c;
        a=find(a);
        b=find(b);
        if(a!=b){
            res+=c;
            p[a]=b;
            cnt++;
        }
    }
    if(cnt<n-1) return INF;
    else return res;
}
int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        edge[i]={a,b,c};
    }
    sort(edge+1,edge+1+m,cmp);
    int t=kruskal();
    if (t==INF) puts("impossible");
    else printf("%d\n",t);

  return 0;
}
//  freopen("testdata.in", "r", stdin);

各种容器

unorder_map

简单例子

unordered_map<string,int>m;
    m["s"]=54;
    cout<<m.count("s")<<endl;
    cout<<m["s"]<<endl;

priority_queue

小根堆优先队列定义方法

priority_queue<int,vector<int>,greater<int> >q;

string

https://www.cnblogs.com/OfflineBoy/p/13658526.html

数论

867. 分解质因数

https://www.acwing.com/problem/content/869/

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
void fun(int x){
    for(int i=2;i<=x/i;i++){ 
        if(x%i==0){
            int s=0;
            while(x%i==0){
                s++;
                x/=i;
            }
            cout<<i<<' '<<s<<endl;
        }
    }
    if (x>1) cout<< x <<' '<<1<<endl;
    cout<<endl;
}
int main(){
    int n;
    cin>>n;
    while(n--){
        int x;
        cin>>x;
        fun(x);
    }
  return 0;
}
//  freopen("testdata.in", "r", stdin);

869. 试除法求约数

https://www.acwing.com/problem/content/871/

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
vector<int> fun(int n){
    vector<int> res;
    for(int i=1;i<=n/i;i++){
        if(n%i==0){
            res.push_back(i);
            //如果n能整除i,那么也能整除n/i
            if(i!=n/i){
                res.push_back(n/i);
            }
        }
    }
    sort(res.begin(),res.end());
    return res;
}
int main(){
    int n;
    cin>>n;
    while(n--){
        int x;
        cin>>x;
        auto res=fun(x);
        for(auto i:res){
            cout<<i<<" ";
        }
        cout<<endl;
    }
  return 0;
}
//  freopen("testdata.in", "r", stdin);

870. 约数个数

https://www.acwing.com/problem/content/872/

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int mod=1e9+7;
int n;
int main(){
    cin>>n;
    unordered_map<int,int>primes;
    LL ans=1;
    while(n--){
        int x;
        cin>>x;
        for(int i=2;i<=x/i;i++){
            while(x%i==0){
                x/=i;
                primes[i]++;
            }
        }
        if(x>1) primes[x]++;
    }
    for(auto prime:primes){
            ans=ans*(prime.second+1)%mod;
        }
    cout<<ans<<endl;
  return 0;
}
//  freopen("testdata.in", "r", stdin);

871. 约数之和

https://www.acwing.com/problem/content/873/

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int mod=1e9+7;
int main(){
    int n;
    cin>>n;
    unordered_map<int,int>primes;
    while(n--){
        int x;
        cin>>x;
        for(int i=2;i<=x/i;i++){
            while(x%i==0){
                x/=i;
                primes[i]++;
            }
        }
        if (x>1) primes[x] ++ ;
    }
    LL res=1;
    for(auto prime: primes){
        int p=prime.first,a=prime.second;
        LL t=1;;
        while(a--){
            t=(t*p+1)%mod;
            //t=1时 乘一次就是p+1 乘两次就是p平方+p+1
        }
        res=res*t%mod;
    }
    cout<<res<<endl;
  return 0;
}
//  freopen("testdata.in", "r", stdin);

873. 欧拉函数

https://www.acwing.com/video/298/

#include <iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
int fun(int x){
    int res=x;
    for(int i=2;i<=x/i;i++){
        if(x%i==0){
            res=res/i*(i-1);//先除后乘 避免数据溢出
            while(x%i==0) x/=i;
        }
    }
    if(x>1) res=res/x*(x-1);
    return res;
}
int main(){
    int n;
    cin>>n;
    while(n--){
        int a;
        scanf("%d",&a);
        cout<<fun(a)<<endl;
    }
  return 0;
}
//  freopen("testdata.in", "r", stdin);

线性筛法

#include<cstdio>
#include<iostream>
using namespace std;
int check[100000001];
int prime[1000001];
int main()
{
	int n,q;
	int cnt=0;
	//根据n<=10^8,q<=10^6开对应的数组大小,防止MLE
	//初始将check数组全部标记为0,标0的是素数,标1的不是素数
	scanf("%d%d",&n,&q);
	check[1]=1;//1不是素数
	for(int i=2;i<=n;i++)
	{
		if(!check[i])prime[cnt++]=i;//若当前数i没有被之前的所有数筛掉,表明i是素数,将i添加进素数表prime
		for(int j=0;j<cnt&&i*prime[j]<100000001;j++)//注意i*prime[j]不要超过n的上限(10^8)
		{
			check[i*prime[j]]=1;//将当前素数prime[j]的i倍标记为合数
			if(i%prime[j]==0)break;//关键步骤:保证每个合数只被筛一次
		}
	}
	for(int i=1;i<=q;i++)
	{
		scanf("%d",&n);
		printf("%d\n",prime[n-1]);//由于素数表从0开始存,所以输出时下标应减1
	}
	return 0;
}

int string 互相转换

废物机房用不了to_string
用sstream

#include<sstream>
void i2s(int i,string &str){//str记得是引用
	stringstream ss;
	ss<<i;
	ss>>str;
}

字符串转数字 同理反过来写即可

void fun(int &x,string str){
	stringstream ss;
	ss<<str;
	ss>>x;
}

树状数组

https://www.cnblogs.com/OfflineBoy/p/13520110.html

devc开启C++11

-std=c++11

posted @ 2021-06-03 15:51  一个经常掉线的人  阅读(51)  评论(0)    收藏  举报