KMP

1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 using namespace std;
5 const int maxn=2000;
6 char a[maxn+50],s[maxn+50];
7 int next[maxn+50][maxn+50];
8 int len1,len,t;
9 int main()
10 {
11 scanf("%d\n",&t);
12 while(t--)
13 {
14 s[0]='0';
15 scanf("%s",s+1);
16 len=strlen(s);
17 for(int k=1;k<len;++k)
18 {
19 int j=k-1;
20 next[k][k]=k-1;
21 for(int i=k+1;i<len;++i)
22 {
23 while(j>=k&&s[j+1]!=s[i]) j=next[k][j];
24 if(s[j+1]==s[i]) ++j;
25 next[k][i]=j;
26 }
27 }
28 long long ans=0;
29 for(int k=1;k<len;++k)
30 {
31 int j=k-1;
32 for(int i=1;i<len;++i)
33 {
34 while(j>=k&&s[j+1]!=s[i]) j=next[k][j];
35 if(s[j+1]==s[i]) ++j;
36 ans^=1LL*(i-(j-k+1))*(j-k+1)*(j-k+1)*(len-1-j);
37 if(j==len-1) j=next[k][j];
38 }
39 }
40 printf("%lld\n",ans);
41 }
42 return 0;
43 }
扩展KMP

1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 using namespace std;
5 const int maxn=1e6;
6 char S[maxn+50],T[maxn+50];//S是母串,T是子串
7 int len1,len2;
8 int next[maxn+50],extend[maxn+50];//extend[i]表示S[i..len1-1]和T的最长公共前缀的长度,next[i]表示T[i..len2-1]和T的最长公共前缀的长度
9 void getnext()
10 {
11 next[0]=len2;
12 int j=0;
13 while(j+1<len2&&T[j]==T[j+1]) ++j;
14 next[1]=j;
15 int k=1;
16 for(int i=2;i<len2;++i)
17 {
18 int p=k+next[k]-1,l=next[i-k];
19 if(i+l<p+1) next[i]=l;
20 else
21 {
22 j=max(p-i+1,0);
23 while(i+j<len2&&T[i+j]==T[j]) ++j;
24 next[i]=j;
25 k=i;
26 }
27 }
28 }
29 void ekmp()
30 {
31 int j=0;
32 while(j<len1&&j<len2&&S[j]==T[j]) ++j;
33 extend[0]=j;
34 int k=0;
35 for(int i=1;i<len1;++i)
36 {
37 int p=k+extend[k]-1,l=next[i-k];//p表示到达的最远位置,k是对应最远位置的i
38 if(i+l<p+1) extend[i]=l;
39 else
40 {
41 j=max(p-i+1,0);
42 while(i+j<len1&&j<len2&&S[i+j]==T[j]) ++j;
43 extend[i]=j;
44 k=i;
45 }
46 }
47 }
48 int main()
49 {
50 scanf("%s%s",S,T);
51 len1=strlen(S),len2=strlen(T);
52 getnext();
53 ekmp();
54 for(int i=0;i<len1;++i) printf("%d ",extend[i]);
55 return 0;
56 }
Manacher求最长回文子串

1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 using namespace std;
5 const int maxn=10000;
6 char s[maxn*2+50];
7 int len=1,mx=0,id=0;
8 int p[2*maxn+50];//p[i]表示以i为中心,向两边扩展的最长长度
9 char c;
10 int main()
11 {
12 s[0]='$',s[1]='#';
13 while(scanf("%c",&c)==1) s[++len]=c,s[++len]='#';//在原字符串每个中间插上#,包括头尾,使得回文串长度为奇数,同时为了防止越界,第一个字符设为$
14 for(int i=0;i<=len;++i)
15 {
16 if(mx>i) p[i]=min(p[2*id-i],mx-i);else p[i]=1;
17 while(s[i+p[i]]==s[i-p[i]]) ++p[i];
18 if(i+p[i]>mx)
19 {
20 mx=i+p[i];
21 id=i;
22 }
23 }//O(n)求p数组
24 for(int i=0;i<=len;++i) printf("%d ",p[i]);
25 return 0;
26 }
后缀数组

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=2e5;
4 char s[maxn+50];
5 int sa[maxn+50],rk[maxn+50],height[maxn+50],d[maxn+50][30];
6 int t[maxn+50],t2[maxn+50],c[maxn+50];
7 int len,k;
8 void getsa(int m)//m表示最大字符的编码
9 {
10 memset(t,-1,sizeof(t));
11 memset(t2,-1,sizeof(t2));
12 int *x=t,*y=t2;
13 for(int i=0;i<m;++i) c[i]=0;
14 for(int i=0;i<len;++i) c[x[i]=s[i]]++;
15 for(int i=1;i<m;++i) c[i]+=c[i-1];
16 for(int i=len-1;i>=0;--i) sa[--c[x[i]]]=i;
17 for(int k=1;k<=len;k<<=1)
18 {
19 int p=0;
20 for(int i=len-k;i<len;++i) y[p++]=i;
21 for(int i=0;i<len;++i) if(sa[i]>=k) y[p++]=sa[i]-k;
22 for(int i=0;i<m;++i) c[i]=0;
23 for(int i=0;i<len;++i) c[x[y[i]]]++;
24 for(int i=0;i<m;++i) c[i]+=c[i-1];
25 for(int i=len-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
26 swap(x,y);
27 p=1,x[sa[0]]=0;
28 for(int i=1;i<len;++i)
29 if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]) x[sa[i]]=p-1;else x[sa[i]]=p++;
30 if(p>=len) break;
31 m=p;
32 }
33 }
34 void getheight()
35 {
36 int k=0;
37 for(int i=0;i<len;++i) rk[sa[i]]=i;
38 for(int i=0;i<len;++i)
39 {
40 if(k) --k;
41 if(rk[i]==0) continue;
42 int j=sa[rk[i]-1];
43 while(s[i+k]==s[j+k]) ++k;
44 height[rk[i]]=k;
45 }
46 }
47 void rmq_init()
48 {
49 for(int i=0;i<len;i++) d[i][0]=height[i];
50 for(int j=1;(1<<j)-1<=len;j++)
51 for(int i=0;i+(1<<j)-1<len;i++)
52 d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
53 }
54 int lcp(int l,int r)
55 {
56 if(l<0||r>=len) return 0;
57 l=rk[l],r=rk[r];
58 if(l>r) swap(l,r);
59 ++l;
60 int k=0;
61 while((1<<(k+1))<=r-l+1) k++;
62 return min(d[l][k],d[r-(1<<k)+1][k]);
63 }
64 int main()
65 {
66 scanf("%s",s);
67 len=strlen(s);
68 getsa('z'+1);
69 getheight();
70 rmq_init();
71 int ans=0;
72 for(int l=1;l<=len;++l)
73 for(int i=0;i<len;i+=l)
74 {
75 int m=lcp(i,i+l);
76 ans=max(ans,m/l+1);
77 ans=max(ans,lcp(i-l+m%l,i+m%l)/l+1);
78 }
79 printf("%d\n",ans);
80 // for(int i=0;i<n;++i) printf("%d ",sa[i]);printf("\n");
81 // for(int i=0;i<n;++i) printf("%d ",rk[i]);printf("\n");
82 // for(int i=0;i<n;++i) printf("%d ",height[i]);printf("\n");
83 return 0;
84
85 }
AC自动机

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1e5;
4 int ch[maxn+50][26];
5 int sz=0,n,root=0;
6 char s[maxn+50],S[maxn+50];
7 int danger[maxn+50];
8 int nx[maxn+50];
9 int last[maxn+50];
10 queue<int> q;
11 bool vis[maxn+50];
12 void buildtrie(char *s)
13 {
14 int u=root;
15 int len=strlen(s);
16 for(int i=0;i<len;++i)
17 {
18 int id=s[i]-'a';
19 if(!ch[u][id]) ch[u][id]=++sz;
20 u=ch[u][id];
21 }
22 ++danger[u];
23 }
24 void buildfail()
25 {
26 while(!q.empty()) q.pop();
27 for(int i=0;i<26;++i) if(ch[root][i]) q.push(ch[root][i]),nx[ch[root][i]]=root,last[ch[root][i]]=0;
28 while(!q.empty())
29 {
30 int u=q.front();
31 q.pop();
32 for(int i=0;i<26;++i)
33 if(ch[u][i])
34 {
35 int k=nx[u];
36 while(!ch[k][i]&&k) k=nx[k];
37 nx[ch[u][i]]=ch[k][i];
38 //danger[ch[u][i]]|=danger[ch[k][i]];
39 if(danger[ch[k][i]]) last[ch[u][i]]=ch[k][i];else last[ch[u][i]]=last[ch[k][i]];
40 q.push(ch[u][i]);
41 }
42 else ch[u][i]=u==0?0:ch[nx[u]][i];
43 }
44 }
45 bool query(char *s)
46 {
47 int len=strlen(s);
48 int u=root;
49 int ans=0;
50 for(int i=0;i<len;++i)
51 {
52 int id=s[i]-'a';
53 u=ch[u][id];
54 int v=u;
55 while(v)
56 {
57 if(vis[v]) break;
58 vis[v]=1;
59 if(danger[v]) ans+=danger[v],danger[v]=0;
60 v=last[v];
61 }
62 }
63 return ans==n;
64 }
65 void init()
66 {
67 for(int i=0;i<=sz;++i) memset(ch[i],0,sizeof(ch[i]));
68 for(int i=0;i<=sz;++i) danger[i]=0;
69 for(int i=0;i<=sz;++i) last[i]=0;
70 for(int i=0;i<=sz;++i) nx[i]=0;
71 for(int i=0;i<=sz;++i) vis[i]=0;
72 sz=0;
73 }
74 int main()
75 {
76 int T;
77 scanf("%d",&T);
78 while(T--)
79 {
80 scanf("%d",&n);
81 init();
82 int mx=0;
83 for(int i=1;i<=n;++i)
84 {
85 scanf("%s",s);
86 int l=strlen(s);
87 if(l>mx)
88 {
89 mx=l;
90 strcpy(S,s);
91 }
92 buildtrie(s);
93 }
94 buildfail();
95 if(query(S)) printf("%s\n",S);else printf("No\n");
96 }
97 return 0;
98 }
树链剖分(bzoj1036)

1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 #include<vector>
5 using namespace std;
6 const int maxn=30000,inf=1e9;
7 struct wjmzbmr
8 {
9 int tid,top,size,son,dep,father,v;
10 }tree[maxn+50];
11 struct fotile96
12 {
13 int maxnum,sum;
14 }f[4*maxn+50];
15 vector<int> g[maxn+50];
16 int pos[maxn+50];
17 int n,label=0,q;
18 void dfs(int x,int fa,int dep)
19 {
20 tree[x]=(wjmzbmr){0,0,1,0,dep,fa,tree[x].v};
21 int m=0;
22 for(int i=0;i<g[x].size();++i)
23 if(g[x][i]!=fa)
24 {
25 dfs(g[x][i],x,dep+1);
26 tree[x].size+=tree[g[x][i]].size;
27 if(tree[g[x][i]].size>m) m=tree[g[x][i]].size,tree[x].son=g[x][i];
28 }
29 }
30 void connect(int x,int top)
31 {
32 tree[x].tid=++label,pos[tree[x].tid]=x;
33 tree[x].top=top;
34 if(tree[x].son!=0) connect(tree[x].son,top);
35 for(int i=0;i<g[x].size();++i)
36 if(g[x][i]!=tree[x].father&&g[x][i]!=tree[x].son) connect(g[x][i],g[x][i]);
37 }
38 void make(int k,int l,int r)
39 {
40 if(l>r) return;
41 if(l==r) f[k].maxnum=f[k].sum=tree[pos[l]].v;
42 else
43 {
44 int mid=(l+r)>>1;
45 make(k*2,l,mid);
46 make(k*2+1,mid+1,r);
47 f[k].sum=f[k*2].sum+f[k*2+1].sum;
48 f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum);
49 }
50 }
51 void change(int k,int l,int r,int x,int y)
52 {
53 if(l>r||r<x||l>x) return;
54 if(l==r)
55 {
56 if(l==x) f[k].maxnum=y,f[k].sum=y;
57 return;
58 }
59 int mid=(l+r)>>1;
60 change(k*2,l,mid,x,y);
61 change(k*2+1,mid+1,r,x,y);
62 f[k].sum=f[k*2].sum+f[k*2+1].sum;
63 f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum);
64 }
65 int qqmax(int k,int l,int r,int ll,int rr)
66 {
67 if(l>r||l>rr||r<ll) return -inf;
68 if(l>=ll&&r<=rr) return f[k].maxnum;
69 int mid=(l+r)>>1;
70 return max(qqmax(k*2,l,mid,ll,rr),qqmax(k*2+1,mid+1,r,ll,rr));
71 }
72 int qmax(int x,int y)
73 {
74 int ans=-inf;
75 while(tree[x].top!=tree[y].top)
76 {
77 if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
78 ans=max(ans,qqmax(1,1,n,tree[tree[x].top].tid,tree[x].tid));
79 x=tree[tree[x].top].father;
80 }
81 if(tree[x].dep>tree[y].dep) swap(x,y);
82 ans=max(ans,qqmax(1,1,n,tree[x].tid,tree[y].tid));
83 return ans;
84 }
85 int qqsum(int k,int l,int r,int ll,int rr)
86 {
87 if(l>r||l>rr||r<ll) return 0;
88 if(l>=ll&&r<=rr) return f[k].sum;
89 int mid=(l+r)>>1;
90 return qqsum(k*2,l,mid,ll,rr)+qqsum(k*2+1,mid+1,r,ll,rr);
91 }
92 int qsum(int x,int y)
93 {
94 int ans=0;
95 while(tree[x].top!=tree[y].top)
96 {
97 if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
98 ans+=qqsum(1,1,n,tree[tree[x].top].tid,tree[x].tid);
99 x=tree[tree[x].top].father;
100 }
101 if(tree[x].dep>tree[y].dep) swap(x,y);
102 ans+=qqsum(1,1,n,tree[x].tid,tree[y].tid);
103 return ans;
104 }
105 int main()
106 {
107 scanf("%d",&n);
108 for(int i=1;i<=n;++i) g[i].clear();
109 for(int i=1;i<n;++i)
110 {
111 int x,y;
112 scanf("%d %d",&x,&y);
113 g[x].push_back(y);
114 g[y].push_back(x);
115 }
116 for(int i=1;i<=n;++i) scanf("%d",&tree[i].v);
117 dfs(1,0,0);
118 connect(1,1);
119 make(1,1,n);
120 scanf("%d\n",&q);
121 for(int i=1;i<=q;++i)
122 {
123 int x,y;
124 char s[10];
125 scanf("%s %d %d\n",s,&x,&y);
126 if(s[0]=='C') change(1,1,n,tree[x].tid,y);
127 if(s[1]=='M') printf("%d\n",qmax(x,y));
128 if(s[1]=='S') printf("%d\n",qsum(x,y));
129 }
130 return 0;
131 }
treap实现名次树

1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 #include<ctime>
5 using namespace std;
6 const int maxn=32767;
7 struct xyz111
8 {
9 xyz111* ch[2];
10 int value,key,size;
11 int cmp(int x)
12 {
13 if(value==x) return -1;
14 return value<x;
15 }
16 void maintain()
17 {
18 size=1;
19 if(ch[0]!=NULL) size+=ch[0]->size;
20 if(ch[1]!=NULL) size+=ch[1]->size;
21 }
22 };
23 xyz111* root=NULL;
24 int n;
25 void rorate(xyz111* &o,int d)
26 {
27 xyz111* k=o->ch[d^1];
28 o->ch[d^1]=k->ch[d];
29 k->ch[d]=o;
30 o->maintain();
31 k->maintain();
32 o=k;
33 }
34 void insert(xyz111* &o,int x)
35 {
36 if(o==NULL)
37 {
38 o=new xyz111();
39 o->ch[0]=o->ch[1]=NULL;
40 o->value=x;
41 o->size=1;
42 o->key=rand()%100000000;
43 }
44 else
45 {
46 int d=o->cmp(x);
47 if(d==-1) return;
48 insert(o->ch[d],x);
49 if(o->ch[d]->key>o->key) rorate(o,d^1);
50 }
51 o->maintain();
52 }
53 int kth(xyz111* o,int k)
54 {
55 int l=0;
56 if(o->ch[0]!=NULL) l=o->ch[0]->size;
57 if(l+1==k) return o->value;
58 if(l+1>k) return kth(o->ch[0],k);
59 return kth(o->ch[1],k-l-1);
60 }
61 int rank(xyz111* o,int x)
62 {
63 if(o==NULL) return 0;
64 int d=o->cmp(x),l=0;
65 if(o->ch[0]!=NULL) l=o->ch[0]->size;
66 if(d==-1) return l+1;
67 if(d==0) return rank(o->ch[0],x);
68 return l+1+rank(o->ch[1],x);
69 }
70 int main()
71 {
72 scanf("%d",&n);
73 int ans;
74 scanf("%d",&ans);
75 insert(root,ans);
76 for(int i=2;i<=n;++i)
77 {
78 int x;
79 scanf("%d",&x);
80 int k=rank(root,x);
81 if(k==0) ans+=kth(root,1)-x;
82 else
83 if(k==root->size) ans+=x-kth(root,root->size);
84 else
85 ans+=min(x-kth(root,k),kth(root,k+1)-x);
86 insert(root,x);
87 }
88 printf("%d",ans);
89 return 0;
90 }
匈牙利算法

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=2000;
4 vector<int> g[maxn+5];
5 bool v[maxn+5];
6 int f[maxn+5];
7 int n,m;
8 void addedge(int u,int v)
9 {
10 g[u].push_back(v);
11 g[v].push_back(u);
12 }
13 bool dfs(int k)
14 {
15 for(int i=0;i<g[k].size();++i)
16 if(v[g[k][i]]==0)
17 {
18 v[g[k][i]]=1;
19 if(f[g[k][i]]==0||dfs(f[g[k][i]]))
20 {
21 f[g[k][i]]=k;
22 f[k]=g[k][i];
23 return true;
24 }
25 }
26 return false;
27 }
28 int main()
29 {
30 scanf("%d %d",&n,&m);
31 for(int i=0;i<=n+m;++i) g[i].clear();
32 for(int i=n+1;i<=m+n;++i)
33 {
34 int x,y;
35 scanf("%d %d",&x,&y);
36 ++x,++y;
37 addedge(i,x);
38 addedge(i,y);
39 }
40 memset(f,0,sizeof(f));
41 int ans=0;
42 for(int i=1;i<=n+m;++i)
43 {
44 if(f[i]!=0) continue;
45 memset(v,0,sizeof(v));
46 if(dfs(i)) ++ans;
47 }
48 printf("%d",ans);
49 return 0;
50 }
有向图强连通(两次DFS)

1 #include<cstring>
2 #include<cstdio>
3 #include<algorithm>
4 #include<vector>
5 using namespace std;
6 const int maxn=1e5,inf=1e9;
7 vector < int > g[maxn+50],g1[maxn+50],g2[maxn+50];
8 bool v[maxn+50];
9 int n,m,color[maxn+50],t[maxn+50],len,c,d[maxn+50];
10 void dfs(int k)
11 {
12 v[k]=1;
13 for(int i=0;i<g[k].size();++i)
14 if(!v[g[k][i]]) dfs(g[k][i]);
15 ++len;
16 t[len]=k;
17 }
18 void dfs1(int k)
19 {
20 v[k]=1;
21 color[k]=c;
22 for(int i=0;i<g1[k].size();++i)
23 if(!v[g1[k][i]]) dfs1(g1[k][i]);
24 }
25 bool check2(int a,int b)
26 {
27 if(a==b) return 0;
28 for(int i=0;i<g2[a].size();++i)
29 if(g2[a][i]==b) return 0;
30 return 1;
31 }
32 int main()
33 {
34
35 while(scanf("%d %d",&n,&m)!=EOF)
36 {
37 c=0;
38 len=0;
39 memset(d,0,sizeof(d));
40 for(int i=0;i<=n;++i) g[i].clear(),g1[i].clear(),g2[i].clear();
41 for(int i=1;i<=m;++i)
42 {
43 int x,y;
44 scanf("%d %d",&x,&y);
45 g[x].push_back(y);
46 g1[y].push_back(x);
47 }
48 memset(v,0,sizeof(v));
49 memset(t,0,sizeof(t));
50 for(int i=1;i<=n;++i) if(!v[i]) dfs(i);
51 memset(v,0,sizeof(v));
52 for(int i=len;i>=1;--i) if(!v[t[i]]) ++c,dfs1(t[i]);
53 for(int i=1;i<=n;++i)
54 for(int j=0;j<g[i].size();++j)
55 if(check2(color[i],color[g[i][j]]))
56 g2[color[i]].push_back(color[g[i][j]]),++d[color[i]];
57 int s=0,x=0;
58 for(int i=1;i<=c;++i) if(d[i]==0) ++s,x=i;
59 if(s>1) printf("0\n");
60 else
61 {
62 int ans=0;
63 for(int i=1;i<=n;++i)
64 if(color[i]==x) ++ans;
65 printf("%d\n",ans);
66 }
67 }
68 return 0;
69 }
70 /*bitset优化*/
71 void dfs(int k)
72 {
73 if(vis[k]==0) return;
74 vis.reset(k);
75 bitset<maxn+5> nx=vis&g[k];
76 int u=nx._Find_first();
77 while(u<=n)
78 {
79 dfs(u);
80 u=nx._Find_next(u);
81 }
82 a.push_back(k);
83 }
84 void dfs1(int k)
85 {
86 if(vis[k]==0) return;
87 vis.reset(k);
88 bitset<maxn+5> nx=vis&g1[k];
89 int u=nx._Find_first();
90 while(u<=n)
91 {
92 dfs1(u);
93 u=nx._Find_next(u);
94 }
95 }
无向图的点双联通分量

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1000,maxm=1000000;
4 vector<int> g[maxn+50],bcc[maxn+50];
5 int dfstime[maxn+50],low[maxn+50],color[maxn+50],head[maxn+50];
6 bool p[maxn+5][maxn+5],map[maxn+5][maxn+5],flag;
7 int n,m,top,c,t;
8 bool ins[maxn+50];
9 struct wjmzbmr
10 {
11 int u,v;
12 }s[maxm];
13 void tarjan(int k,int fa)
14 {
15 low[k]=dfstime[k]=++t;
16 for(int i=0;i<g[k].size();++i)
17 {
18 int u=g[k][i];
19 if(u==fa) continue;
20 if(dfstime[u])
21 if(dfstime[u]<dfstime[k]) low[k]=min(low[k],dfstime[u]),s[++top]={k,u};
22 else;
23 else
24 {
25 s[++top]={k,u};
26 tarjan(u,k);
27 low[k]=min(low[k],low[u]);
28 if(low[u]>=dfstime[k])
29 {
30 ++c;
31 while(1)
32 {
33 wjmzbmr e=s[top--];
34 if(color[e.u]!=c)
35 {
36 bcc[c].push_back(e.u);
37 color[e.u]=c;
38 }
39 if(color[e.v]!=c)
40 {
41 bcc[c].push_back(e.v);
42 color[e.v]=c;
43 }
44 if(e.u==k&&e.v==u) break;
45 }
46 }
47 }
48 }
49 }
50 int main()
51 {
52 scanf("%d %d",&n,&m);
53 while(!(n==0&&m==0))
54 {
55 for(int i=0;i<=n;++i) g[i].clear(),bcc[i].clear();
56 memset(p,0,sizeof(p));
57 for(int i=1;i<=m;++i)
58 {
59 int x,y;
60 scanf("%d %d",&x,&y);
61 p[x][y]=p[y][x]=1;
62 }
63 for(int i=1;i<=n;++i)
64 for(int j=1;j<=n;++j)
65 if(i!=j&&!p[i][j]) g[i].push_back(j);
66 memset(dfstime,0,sizeof(dfstime));
67 memset(s,0,sizeof(s));
68 memset(color,0,sizeof(color));
69 top=c=t=0;
70 for(int i=1;i<=n;++i)
71 if(!dfstime[i]) tarjan(i,-1);
72 scanf("%d %d",&n,&m);
73 }
74 return 0;
75 }
无向图的边双联通分量

1 #include<bits\stdc++.h>
2 using namespace std;
3 const int maxn=4e5;
4 struct wjmzbmr
5 {
6 int x,y,pos;
7 };
8 wjmzbmr e[2*maxn+50];
9 vector<int> g[maxn+50];
10 int dfstime[maxn+50],low[maxn+50],s[maxn+50],color[maxn+50],num[maxn+50];
11 int n,m,top,c,t,ans1=0;
12 bool ins[maxn+50];
13 void tarjan(int k,int fa)
14 {
15 low[k]=dfstime[k]=++t;
16 s[++top]=k;
17 ins[k]=1;
18 for(int i=0;i<g[k].size();++i)
19 {
20 int u=e[g[k][i]].y;
21 if(fa==u) continue;
22 if(!dfstime[u])
23 {
24 tarjan(u,k);
25 //if(low[u]>dfstime[k]) p[g[k][i]]=1; 判断此边是否为桥
26 low[k]=min(low[k],low[u]);
27 }
28 else
29 if(ins[u]) low[k]=min(low[k],low[u]);
30 }
31 if(dfstime[k]==low[k])
32 {
33 ++c;
34 while(1)
35 {
36 int v=s[top--];
37 ins[v]=0,color[v]=c,++num[c];
38 if(v==k) break;
39 }
40 }
41 }
42 int main()
43 {
44 scanf("%d %d",&n,&m);
45 for(int i=0;i<=n;++i) g[i].clear();
46 for(int i=1;i<=m;++i)
47 {
48 int x,y;
49 scanf("%d %d",&x,&y);
50 g[x].push_back(2*i-1),g[y].push_back(2*i);
51 e[2*i-1]={x,y,i},e[2*i]={y,x,i};
52 }
53 memset(dfstime,0,sizeof(dfstime));
54 for(int i=1;i<=n;++i) low[i]=n+1;
55 memset(color,0,sizeof(color));
56 memset(num,0,sizeof(num));
57 memset(s,0,sizeof(s));
58 memset(ins,0,sizeof(ins));
59 top=c=t=0;
60 tarjan(1,-1);
61 return 0;
62 }
求凸包

1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 using namespace std;
5 const int maxn=50000;
6 struct wjmzbmr
7 {
8 int x,y;
9 bool operator < (const wjmzbmr& a) const
10 {
11 return (x<a.x)||(x==a.x&&y<a.y);
12 }
13 }a[maxn+50];
14 int n,s[maxn+50],q[maxn+50],m=0,len=0;
15 int cross(int x1,int y1,int x2,int y2)
16 {
17 return (x1*y2-y1*x2);
18 }
19 int main()
20 {
21 scanf("%d",&n);
22 for(int i=1;i<=n;++i) scanf("%d %d",&a[i].x,&a[i].y);
23 sort(a+1,a+n+1);
24 m=2;
25 s[1]=1,s[2]=2;
26 for(int i=3;i<=n;++i)
27 {
28 while(m>=2&&cross(a[s[m]].x-a[s[m-1]].x,a[s[m]].y-a[s[m-1]].y,a[i].x-a[s[m]].x,a[i].y-a[s[m]].y)<=0) --m;
29 s[++m]=i;
30 }
31 s[++m]=n-1;
32 int k=m;
33 for(int i=n-2;i>=1;--i)
34 {
35 while(m>=k&&cross(a[s[m]].x-a[s[m-1]].x,a[s[m]].y-a[s[m-1]].y,a[i].x-a[s[m]].x,a[i].y-a[s[m]].y)<=0) --m;
36 s[++m]=i;
37 }
38 int ans=0;
39 for(int i=1;i<=m-1;++i)
40 for(int j=i+1;j<=m;++j)
41 if((a[s[i]].x-a[s[j]].x)*(a[s[i]].x-a[s[j]].x)+(a[s[i]].y-a[s[j]].y)*(a[s[i]].y-a[s[j]].y)>ans) ans=(a[s[i]].x-a[s[j]].x)*(a[s[i]].x-a[s[j]].x)+(a[s[i]].y-a[s[j]].y)*(a[s[i]].y-a[s[j]].y);
42 printf("%d",ans);
43 return 0;
44 }
主席树求区间k小

1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 using namespace std;
5 const int maxn=2000;
6 struct wjmzbmr
7 {
8 int l,r,ls,rs,sum;
9 }f[maxn*20];
10 struct fotile96
11 {
12 int l,r,mid;
13 }stack[maxn+50];
14 int a[maxn+50],sorta[maxn+50],root[maxn+50],n,len=0;
15 int build(int l,int r)
16 {
17 int k=++len;
18 f[k].l=l,f[k].r=r,f[k].ls=f[k].rs=f[k].sum=0;
19 if(l==r) return len;
20 int mid=(l+r)>>1;
21 f[k].ls=build(l,mid);
22 f[k].rs=build(mid+1,r);
23 return k;
24 }
25 int change(int root,int x)
26 {
27 int k=++len;
28 f[k]=f[root],f[k].sum+=1;
29 if(f[k].l==f[k].r) return k;
30 int mid=(f[k].l+f[k].r)>>1;
31 if(x<=mid) f[k].ls=change(f[k].ls,x);else f[k].rs=change(f[k].rs,x);
32 return k;
33 }
34 int ask(int a,int b,int k)
35 {
36 if(f[b].l==f[b].r) return f[b].r;
37 int mid=f[f[b].ls].sum-f[f[a].ls].sum;
38 if(k<=mid) return ask(f[a].ls,f[b].ls,k);else return ask(f[a].rs,f[b].rs,k-mid);
39 }
40 int main()
41 {
42 scanf("%d",&n);
43 for(int i=1;i<=n;++i) scanf("%d",&a[i]);
44 for(int i=1;i<=n;++i) sorta[i]=a[i];
45 sort(sorta+1,sorta+n+1);
46 int q=1;
47 for(int i=2;i<=n;++i) if(sorta[i]!=sorta[q]) sorta[++q]=sorta[i];
48 root[0]=build(1,q);
49 for(int i=1;i<=n;++i)
50 {
51 int x=lower_bound(sorta+1,sorta+q+1,a[i])-sorta;
52 root[i]=change(root[i-1],x);
53 }
54 len=1;
55 stack[len].l=stack[len].r=1,stack[len].mid=a[1];
56 for(int i=2;i<=n;++i)
57 {
58 ++len;
59 stack[len].l=stack[len].r=i,stack[len].mid=a[i];
60 while (len>1&&stack[len].mid<stack[len-1].mid)
61 {
62 stack[len-1].r=stack[len].r;
63 --len;
64 stack[len].mid=sorta[ask(root[stack[len].l-1],root[stack[len].r],(stack[len].r-stack[len].l+1)/2+1)];
65 }
66 }
67 int ans=0;
68 for (int i=1;i<=len;++i)
69 for (int j=stack[i].l;j<=stack[i].r;++j)
70 ans+=abs(a[j]-stack[i].mid);
71 printf("%d",ans);
72 return 0;
73 }
主席舒求区间k小(带修改)

1 //时间是O(nlog^2n)
2 //空间也是O(nlog^2n),不过可以采用地址回收
3 #include<cstring>
4 #include<algorithm>
5 #include<cstdio>
6 #include<vector>
7 using namespace std;
8 const int maxn=5e4;
9 vector<int> L,R;
10 int sorta[maxn*2+50],a[maxn*2+50],rk[maxn+50];
11 int ch[maxn*20*20+50][2],sum[maxn*20*20+50],root[maxn+50];
12 int sz=0,len=0;
13 int n,m,T;
14 int lowbit(int x)
15 {
16 return x&(-x);
17 }
18 int change(int last,int l,int r,int x,int type)//type=1表示加上x,type=-1表示减去x
19 {
20 int k=++len;
21 ch[k][0]=ch[last][0],ch[k][1]=ch[last][1],sum[k]=sum[last]+type;
22 if(l==r) return k;
23 int mid=(l+r)>>1;
24 if(x<=mid) ch[k][0]=change(ch[last][0],l,mid,x,type);else ch[k][1]=change(ch[last][1],mid+1,r,x,type);
25 return k;
26 }
27 int query(int l,int r,int k)//询问[l,R]之间的第k小的值
28 {
29 if(l==r) return l;
30 int suml=0,sumr=0;
31 for(int i=0;i<L.size();++i) suml+=sum[ch[L[i]][0]];
32 for(int i=0;i<R.size();++i) sumr+=sum[ch[R[i]][0]];
33 int mid=(l+r)>>1;
34 if(k<=sumr-suml)
35 {
36 for(int i=0;i<L.size();++i) L[i]=ch[L[i]][0];
37 for(int i=0;i<R.size();++i) R[i]=ch[R[i]][0];
38 return query(l,mid,k);
39 }
40 else
41 {
42 for(int i=0;i<L.size();++i) L[i]=ch[L[i]][1];
43 for(int i=0;i<R.size();++i) R[i]=ch[R[i]][1];
44 return query(mid+1,r,k-(sumr-suml));
45 }
46 }
47 int main()
48 {
49 scanf("%d",&T);
50 while(T--)
51 {
52 scanf("%d%d",&n,&m);
53 for(int i=1;i<=n;++i) scanf("%d",&a[i]),sorta[i]=a[i];
54 sort(sorta+1,sorta+n+1);
55 len=0,sz=1;
56 rk[1]=sorta[1];
57 for(int i=2;i<=n;++i) if(sorta[i]!=sorta[i-1]) sorta[++sz]=sorta[i],rk[sz]=sorta[i];//离散
58 memset(root,0,sizeof(root));
59 for(int i=1;i<=n;++i)
60 {
61 int id=lower_bound(sorta+1,sorta+sz+1,a[i])-sorta;
62 for(int j=i;j<=n;j+=lowbit(j))
63 root[j]=change(root[j],1,sz,id,1);//每个点自己建
64 }
65 while(m--)
66 {
67 char c=' ';
68 int x,y,k;
69 while(c!='Q'&&c!='C') c=getchar();
70 if(c=='C')
71 {
72 scanf("%d%d",&x,&y);
73 int id=lower_bound(sorta+1,sorta+sz+1,a[x])-sorta;
74 for(int i=x;i<=n;i+=lowbit(i)) root[i]=change(root[i],1,sz,id,-1);
75 a[x]=y;
76 id=lower_bound(sorta+1,sorta+sz+1,a[x])-sorta;
77 for(int i=x;i<=n;i+=lowbit(i)) root[i]=change(root[i],1,sz,id,1);
78 }
79 else
80 {
81 scanf("%d%d%d",&x,&y,&k);
82 L.clear(),R.clear();
83 for(int i=x-1;i;i-=lowbit(i)) L.push_back(root[i]);
84 for(int i=y;i;i-=lowbit(i)) R.push_back(root[i]);
85 printf("%d\n",rk[query(1,sz,k)]);
86 }
87 }
88 }
89 return 0;
90 }
dinic

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=2000,inf=1e9,maxm=90000;
4 struct Edge
5 {
6 int from,to,cap,flow;
7 }edge[maxm*2+5];;
8 vector <int> g[maxn+5];
9 int step[maxn];//从源点到点x的距离
10 int iter[maxn];//定点x的第几条边开始有用
11 int n,m,S,T,len;
12 void addedge(int from,int to,int cap)
13 {
14 ++len;
15 edge[len]={from,to,cap,0};
16 g[from].push_back(len);
17 ++len;
18 edge[len]={to,from,0,0};
19 g[to].push_back(len);
20 }
21 void bfs(int S)
22 {
23 memset(step,-1,sizeof(step));
24 step[S]=0;
25 queue<int> q;
26 q.push(S);
27 while(!q.empty())
28 {
29 int v=q.front();
30 q.pop();
31 for(int i=0;i<g[v].size();++i)
32 {
33 Edge &e=edge[g[v][i]];
34 if(e.cap>e.flow&&step[e.to]<0)
35 {
36 step[e.to]=step[v]+1;
37 q.push(e.to);
38 }
39 }
40 }
41 }
42 int dfs(int v,int t,int f)
43 {
44 if(v==t) return f;
45 for(int &i=iter[v];i<g[v].size();++i)//这里是引用,i++的同时iter也++,其实相当于上个的used,不过不用判断了
46 {
47 Edge &e=edge[g[v][i]];
48 if(e.cap>e.flow&&step[e.to]>step[v])
49 {
50 int d=dfs(e.to,t,min(e.cap-e.flow,f));
51 if(d>0)
52 {
53 e.flow+=d;
54 edge[g[v][i]^1].flow-=d;
55 return d;
56 }
57 }
58 }
59 return 0;
60 }
61 int maxflow(int S,int T)
62 {
63 int flow=0;
64 for(;;)
65 {
66 bfs(S);
67 if(step[T]<0) return flow;
68 memset(iter,0,sizeof(iter));
69 int f;
70 while((f=dfs(S,T,inf))>0)
71 flow+=f;
72 }
73 }
74 int main()
75 {
76 scanf("%d%d",&n,&m);
77 S=0,T=n+1;
78 for(int i=0;i<=T;++i) g[i].clear();
79 len=-1;
80 for(int i=1;i<=n;++i)
81 {
82 int x;
83 scanf("%d",&x);
84 if(x==0) addedge(S,i,1);else addedge(i,T,1);
85 }
86 for(int i=0;i<m;++i)
87 {
88 int u,v;
89 scanf("%d%d",&u,&v);
90 addedge(u,v,1);
91 addedge(v,u,1);
92 }
93 printf("%d\n",maxflow(S,T));
94 return 0;
95 }
最大费用最大流(可行流)

1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 #include<cmath>
5 #include<vector>
6 #include<queue>
7 using namespace std;
8 const int maxn=200,maxm=5000,inf=1e7;
9 const double eps=1e-12;
10 struct wjmzbmr
11 {
12 int from,to,cap,flow;
13 double cost;
14 }edge[8*maxm];
15 vector<int> g[maxn+50];
16 double d[maxn+50];
17 int a[maxn+50],b[maxn+50],last[maxn+50],f[maxn+50];
18 int n,m,t,len,S,T;
19 bool v[maxn+50];
20 void add(int from,int to,int cap,double cost)
21 {
22 edge[++len]=(wjmzbmr){from,to,cap,0,cost},g[from].push_back(len);
23 edge[++len]=(wjmzbmr){to,from,0,0,-cost},g[to].push_back(len);
24 }
25 bool spfa(int S,int T,int &flow,double &cost)
26 {
27 for(int i=0;i<=n+1;++i) d[i]=(double)-inf,f[i]=inf;
28 memset(v,0,sizeof(v));
29 d[S]=0.0,v[S]=1,last[S]=0,f[S]=inf;
30 queue<int> q;
31 while(!q.empty()) q.pop();
32 q.push(S);
33 while(!q.empty())
34 {
35 int u=q.front();
36 q.pop();
37 v[u]=0;
38 for(int i=0;i<g[u].size();++i)
39 {
40 wjmzbmr& e=edge[g[u][i]];
41 if(e.cap>e.flow&&(d[e.to]+eps<d[u]+e.cost))
42 {
43 d[e.to]=d[u]+e.cost;
44 last[e.to]=g[u][i];
45 f[e.to]=min(f[u],e.cap-e.flow);
46 if(!v[e.to])
47 {
48 q.push(e.to);
49 v[e.to]=1;
50 }
51 }
52 }
53 }
54 if(d[T]==-inf) return false;
55 //if(d[T]*f[T]<0) return false;最大费用可行流
56 flow+=f[T];
57 cost+=d[T]*f[T];
58 int u=T;
59 while(u!=S)
60 {
61 edge[last[u]].flow+=f[T];
62 edge[last[u]^1].flow-=f[T];
63 u=edge[last[u]].from;
64 }
65 return true;
66 }
67 int main()
68 {
69 scanf("%d",&t);
70 while(t--)
71 {
72 scanf("%d %d",&n,&m);
73 len=-1;
74 for(int i=0;i<=n;++i) g[i].clear();
75 for(int i=1;i<=n;++i) scanf("%d %d",&a[i],&b[i]);
76 for(int i=1;i<=m;++i)
77 {
78 int x,y,z;double p;
79 scanf("%d %d %d %lf",&x,&y,&z,&p);
80 p=log2(1.0-p);
81 if(z==0) continue;
82 else
83 {
84 add(x,y,1,0);
85 add(x,y,z-1,p);
86 }
87 }
88 S=0,T=n+1;
89 for(int i=1;i<=n;++i)
90 {
91 if(a[i]-b[i]==0) continue;
92 if(a[i]-b[i]>0) add(S,i,a[i]-b[i],0);
93 else add(i,T,b[i]-a[i],0);
94 }
95 int flow=0;double cost=0.0;
96 while(spfa(S,T,flow,cost)) ;
97 printf("%.2f\n",1.0-pow(2.0,cost));
98 }
99 return 0;
100 }
高斯消元

1 /*
2 n个未知数,m个方程
3 */
4 #include<bits/stdc++.h>
5 using namespace std;
6 const int maxn=1000;
7 const double eps=1e-6;
8 double a[maxn+5][maxn+5];
9 int n,m;
10 int main()
11 {
12 scanf("%d%d",&n,&m);
13 for(int i=1;i<=m;++i)
14 for(int j=1;j<=n+1;++j)
15 scanf("%lf",&a[i][j]);
16 for(int i=1;i<=n;++i)//枚举列
17 {
18 if(fabs(a[i][i]-0.0)<=eps)
19 {
20 int j;
21 bool flag=0;
22 for(j=i+1;j<=m;++j)
23 if(fabs(a[j][i]-0.0)>eps)
24 {
25 flag=1;
26 break;
27 }
28 if(!flag) return 0*printf("Many solutions");//如果第i~m行的第i列都是0,那么多解
29 for(int k=1;k<=n+1;++k) swap(a[i][k],a[j][k]);
30 }
31 for(int j=1;j<=n+1;++j) if(i!=j)a[i][j]/=a[i][i];a[i][i]=1.0;
32 for(int j=1;j<=m;++j)
33 if(j!=i)
34 {
35 for(int k=1;k<=n+1;++k) if(k!=i) a[j][k]-=a[i][k]*a[j][i];a[j][i]=0.0;
36 }
37 }
38 for(int i=n+1;i<=m;++i)
39 if(fabs(a[i][n+1]-0.0)>eps) return 0*printf("No solutions");//n+1~m这些方程应该所有变量都被消干净了,所以如果不为0,则说明无解
40 for(int i=1;i<=n;++i) printf("%d\n",(int)(a[i][n+1]+0.5));
41 return 0;
42 }
求行列式

1 const int maxn=1000;
2 ll a[maxn+5][maxn+5];
3 int turn,n;
4 void gcd(ll a,ll b,ll &d,ll &x,ll &y)
5 {
6 if(!b) d=a,x=1,y=0;
7 else
8 {
9 ++turn;
10 gcd(b,a%b,d,y,x);
11 y-=x*(a/b);
12 }
13 }
14 ll det(ll n)
15 {
16 //求行列式a[0..n-1][0..n-1]
17 ll tmp1[maxn+5],tmp2[maxn+5];
18 ll ans=1;
19 for(int i=0;i<n;++i)
20 {
21 for(int j=i+1;j<n;++j)
22 if(a[j][i]!=0)
23 {
24 ll A=a[i][i],B=a[j][i],d,x,y;
25 turn=0;
26 gcd(A,B,d,x,y);
27 for(int k=0;k<n;++k) tmp1[k]=a[i][k],tmp2[k]=a[j][k];
28 for(int k=0;k<n;++k) a[i][k]=(x*tmp1[k]+y*tmp2[k])%mod;
29 A/=d,B/=d;
30 if(turn&1) x=B,y=-A,ans=-ans%mod;else x=-B,y=A;
31 for(int k=0;k<n;++k) a[j][k]=(x*tmp1[k]+y*tmp2[k])%mod;
32 }
33 ans=ans*a[i][i]%mod;
34 }
35 if(ans<0) ans+=mod;
36 return ans;
37 }
splay维护数列问题

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=2e5,inf=1e9;
4 int pre[maxn+50],ch[maxn+50][2],flip[maxn+50],key[maxn+50],sz[maxn+50],mi[maxn+50],add[maxn+50];
5 int a[maxn+50];
6 int n,root=0,len=0,m;
7 struct wjmzbmr
8 {
9 int num,id;
10 bool operator < (const wjmzbmr& x) const
11 {
12 return num<x.num||(num==x.num&&id<x.id);
13 }
14 }b[maxn+50];
15 void update(int k)
16 {
17 int l=ch[k][0],r=ch[k][1];
18 sz[k]=1+sz[l]+sz[r];
19 mi[k]=min(key[k],min(mi[l],mi[r]));
20 }
21 void pushdown(int k)
22 {
23 int& l=ch[k][0];
24 int& r=ch[k][1];
25 if(add[k])
26 {
27 if(l) add[l]+=add[k],mi[l]+=add[k],key[l]+=add[k];
28 if(r) add[r]+=add[k],mi[r]+=add[k],key[r]+=add[k];
29 add[k]=0;
30 }
31 if(flip[k])
32 {
33 flip[k]=0;
34 swap(l,r);
35 if(l) flip[l]^=1;
36 if(r) flip[r]^=1;
37 }
38 }
39 void rorate(int k,int d)
40 {
41 int f=pre[pre[k]],p=pre[k];
42 pushdown(p),pushdown(k);
43 ch[p][d^1]=ch[k][d];
44 pre[ch[k][d]]=p;
45 ch[k][d]=p;
46 pre[k]=f;
47 pre[p]=k;
48 if(f) ch[f][ch[f][1]==p]=k;else root=k;
49 update(p),update(k);
50 }
51 void splay(int x,int goal)
52 {
53 pushdown(x);
54 while(pre[x]!=goal)
55 {
56 pushdown(x);
57 if(pre[pre[x]]==goal) rorate(x,ch[pre[x]][0]==x);
58 else
59 {
60 int d1=ch[pre[x]][0]==x,d2=ch[pre[pre[x]]][0]==pre[x];
61 if(d1==d2) rorate(pre[x],d2),rorate(x,d1);
62 else rorate(x,d1),rorate(x,d2);
63 }
64 }
65 update(x);
66 if(goal==0) root=x;
67 }
68 int build(int l,int r,int fa)
69 {
70 if(l>r) return 0;
71 if(l==r)
72 {
73 pre[l]=fa,ch[l][0]=ch[l][1]=0,add[l]=flip[l]=0,key[l]=mi[l]=a[l],sz[l]=1;
74 return l;
75 }
76 int mid=(l+r)>>1;
77 pre[mid]=fa,ch[mid][0]=ch[mid][1]=0,add[mid]=flip[mid]=0,key[mid]=mi[mid]=a[mid],sz[mid]=1;
78 ch[mid][0]=build(l,mid-1,mid),ch[mid][1]=build(mid+1,r,mid);
79 update(mid);
80 return mid;
81 }
82 void find(int k,int goal)
83 {
84 int t=root;
85 while(true)
86 {
87 pushdown(t);
88 if(sz[ch[t][0]]+1==k) break;
89 if(k<=sz[ch[t][0]]) t=ch[t][0];else k-=sz[ch[t][0]]+1,t=ch[t][1];
90 }
91 splay(t,goal);
92 }
93 void make(int l,int r,int c)//将区间[l,r]剪掉,接在新序列的第c位后面
94 {
95 find(l-1,0);
96 find(r+1,root);
97 int u=ch[ch[root][1]][0];
98 find(sz[ch[root][0]]+1+sz[u],ch[root][1]);
99 u=ch[ch[root][1]][0];
100 ch[ch[root][1]][0]=0;
101 update(ch[root][1]),update(root);
102 find(c,0);
103 ch[u][1]=ch[root][1],ch[root][1]=u;
104 pre[ch[u][1]]=u,pre[u]=root;
105 update(u),update(root);
106 }
107 int main()
108 {
109 scanf("%d",&n);
110 for(int i=2;i<=n+1;++i) scanf("%d",&a[i]);
111 mi[0]=key[0]=inf;
112 root=build(1,n+2,0);
113 len=n+2;
114 scanf("%d",&m);
115 while(m--)
116 {
117 char s[10];
118 int l,r,x;
119 scanf("%s",s);
120 if(s[0]=='A')//[l,r]加上x
121 {
122 scanf("%d%d%d",&l,&r,&x);
123 ++l,++r;
124 find(l-1,0);
125 find(r+1,root);
126 int u=ch[ch[root][1]][0];
127 add[u]+=x,key[u]+=x,mi[u]+=x;
128 update(ch[root][1]),update(root);
129 }
130 if(s[0]=='R'&&s[3]=='E')//[l,r]反转
131 {
132 scanf("%d%d",&l,&r);
133 ++l,++r;
134 find(l-1,0);
135 find(r+1,root);
136 int u=ch[ch[root][1]][0];
137 flip[u]^=1;
138 }
139 if(s[0]=='R'&&s[3]=='O')//[l,r]循环右移x次
140 {
141 scanf("%d%d%d",&l,&r,&x);
142 ++l,++r;
143 x%=r-l+1;
144 make(l,r-x,x+l-1);
145 }
146 if(s[0]=='I')//在l后插入一个位置,初值为x
147 {
148 scanf("%d%d",&l,&x);
149 ++l;
150 find(l,0);
151 int u=ch[root][1];
152 ++len;
153 pre[len]=root,ch[len][0]=ch[len][1]=0,add[len]=flip[len]=0,key[len]=mi[len]=x,sz[len]=1;
154 ch[root][1]=len;
155 ch[len][1]=u;
156 pre[u]=len;
157 update(len),update(root);
158 }
159 if(s[0]=='D')//删除第i个位置
160 {
161 scanf("%d",&l);
162 ++l;
163 find(l-1,0);
164 find(l+1,root);
165 ch[ch[root][1]][0]=0;
166 update(ch[root][1]),update(root);
167 }
168 if(s[0]=='M')//求[l,r]最小值
169 {
170 scanf("%d%d",&l,&r);
171 ++l,++r;
172 find(l-1,0);
173 find(r+1,root);
174 printf("%d\n",mi[ch[ch[root][1]][0]]);
175 }
176 }
177 return 0;
178 }
LCT

1 struct LCT
2 {
3 int ch[maxn+5][2],fa[maxn+5],flip[maxn+5];
4 int top;
5 int q[maxn+5];
6 int mx[maxn+5];
7 int s1[maxn+5],s3[maxn+5],sz[maxn+5];//sz 实际子树大小 s1 指向某个点的非偏爱子树的大小和 s3 splay内子树中每个点的s1的和
8 void init()
9 {
10 for(int i=1;i<=n;++i) mx[i]=i,sz[i]=1,s3[i]=s1[i]=flip[i]=fa[i]=ch[i][0]=ch[i][1]=0;
11 }
12 bool isroot(int x)
13 {
14 return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
15 }
16 void update(int x)
17 {
18 int l=ch[x][0],r=ch[x][1];
19 mx[x]=x;
20 if(val[mx[l]]>val[mx[x]])mx[x]=mx[l];
21 if(val[mx[r]]>val[mx[x]])mx[x]=mx[r];
22 sz[x]=s3[r]+s1[x]+1;
23 s3[x]=s3[l]+s3[r]+s1[x]+1;
24 }
25 void pushdown(int x)
26 {
27 int l=ch[x][0],r=ch[x][1];
28 if(flip[x])
29 {
30 flip[x]^=1;flip[l]^=1;flip[r]^=1;
31 swap(ch[x][0],ch[x][1]);
32 update(x);
33 }
34 }
35 void rotate(int &x)
36 {
37 int y=fa[x],z=fa[y],l,r;
38 if(ch[y][0]==x) l=0;
39 else l=1;
40 r=l^1;
41 if(!isroot(y))
42 {
43 if(ch[z][0]==y) ch[z][0]=x;
44 else ch[z][1]=x;
45 }
46 fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
47 ch[y][l]=ch[x][r];ch[x][r]=y;
48 update(y);update(x);
49 }
50 void splay(int &x)
51 {
52 top=0;
53 q[++top]=x;
54 for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
55 while(top) pushdown(q[top--]);
56 while(!isroot(x))
57 {
58 int y=fa[x],z=fa[y];
59 if(!isroot(y))
60 {
61 if(ch[y][0]==x^ch[z][0]==y) rotate(x);
62 else rotate(y);
63 }
64 rotate(x);
65 }
66 }
67 void access(int x)
68 {
69 for(int t=0;x;t=x,x=fa[x])
70 {
71 splay(x);
72 s1[x]+=s3[ch[x][1]];
73 ch[x][1]=t;
74 s1[x]-=s3[t];
75 update(x);
76 }
77 }
78 void makeroot(int x)
79 {
80 access(x);splay(x);flip[x]^=1;
81 pushdown(x);
82 }
83 bool linked(int x,int y)
84 {
85 //判断点x和点y是否在一个连通块中
86 makeroot(x);access(y);splay(y);
87 return x==y||fa[x];
88 }
89 void link(int x,int y)
90 {
91 makeroot(x);fa[x]=y;
92 access(y),splay(y),s1[y]+=s3[x];
93 update(y);
94 }
95 void cut(int x,int y)
96 {
97 makeroot(x);access(y);splay(y);
98 ch[y][0]=fa[x]=0;
99 sz[y]-=s3[x];
100 s3[y]-=s3[x];
101 update(y);
102 }
103 int findfather(int root,int x)
104 {
105 //返回实际树上以root为根,x的父亲
106 makeroot(root);
107 access(x),splay(x);
108 pushdown(x);
109 int fa=ch[x][0];
110 while(true)
111 {
112 pushdown(fa);
113 if(!ch[fa][1]) break;
114 fa=ch[fa][1];
115 }
116 return fa;
117
118 }
119 int querymax(int x,int y)
120 {
121 makeroot(x);access(y);splay(y);
122 return mx[y];
123 }
124 }lct;
倍增求LCA

1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 using namespace std;
5 int n,q,cnt;
6 int deep[1001],head[1001],dis[1001],fa[1001][11];
7 bool vis[1001];
8 struct data{int to,next,v;}e[2001];
9 void ins(int u,int v,int w)
10 {e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;}
11 void insert(int u,int v,int w)
12 {ins(u,v,w);ins(v,u,w);}
13 void dfs(int x)
14 {
15 vis[x]=1;
16 for(int i=1;i<=9;i++)
17 {
18 if(deep[x]<(1<<i))break;
19 fa[x][i]=fa[fa[x][i-1]][i-1];
20 }
21 for(int i=head[x];i;i=e[i].next)
22 {
23 if(vis[e[i].to])continue;
24 deep[e[i].to]=deep[x]+1;
25 dis[e[i].to]=dis[x]+e[i].v;
26 fa[e[i].to][0]=x;
27 dfs(e[i].to);
28 }
29 }
30 int lca(int x,int y)
31 {
32 if(deep[x]<deep[y])swap(x,y);
33 int d=deep[x]-deep[y];
34 for(int i=0;i<=9;i++)
35 if((1<<i)&d)x=fa[x][i];
36 for(int i=9;i>=0;i--)
37 if(fa[x][i]!=fa[y][i])
38 {x=fa[x][i];y=fa[y][i];}
39 if(x==y)return x;
40 else return fa[x][0];
41 }
42 int main()
43 {
44 scanf("%d%d",&n,&q);
45 for(int i=1;i<n;i++)
46 {
47 int u,v,w;
48 scanf("%d%d%d",&u,&v,&w);
49 insert(u,v,w);
50 }
51 dfs(1);
52 for(int i=1;i<=q;i++)
53 {
54 int x,y;
55 scanf("%d%d",&x,&y);
56 printf("%d\n",dis[x]+dis[y]-2*dis[lca(x,y)]);
57 }
58 return 0;
FFT

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=400000;
4 const double pi=acos(-1.0);
5 int l,m,n,num;
6 int a[maxn+50],b[maxn+50];
7 struct wjmzbmr
8 {
9 double r,i;
10 wjmzbmr(double real=0.0,double image=0.0){r=real;i=image;}
11 wjmzbmr operator + (const wjmzbmr o)
12 {
13 return wjmzbmr(r+o.r,i+o.i);
14 }
15 wjmzbmr operator - (const wjmzbmr o)
16 {
17 return wjmzbmr(r-o.r,i-o.i);
18 }
19 wjmzbmr operator * (const wjmzbmr o)
20 {
21 return wjmzbmr(r*o.r-i*o.i,r*o.i+i*o.r);
22 }
23 };
24 wjmzbmr x1[maxn+50],x2[maxn+50];
25 void brc(wjmzbmr *y,int l)
26 {
27 for(int i=1,j=l/2;i<l-1;i++)
28 {
29 if(i<j) swap(y[i],y[j]);
30 int k=l/2;
31 while(j>=k)j-=k,k/=2;
32 if(j<k) j+=k;
33 }
34 }
35 void fft(wjmzbmr *y,int l,double on)
36 {
37 wjmzbmr u,t;
38 brc(y,l);
39 for(int h=2;h<=l;h<<=1)
40 {
41 wjmzbmr wn(cos(on*2*pi/h),sin(on*2*pi/h));
42 for(int j=0;j<l;j+=h)
43 {
44 wjmzbmr w(1,0);
45 for(int k=j;k<j+h/2;k++)
46 {
47 u=y[k];
48 t=w*y[k+h/2];
49 y[k]=u+t;
50 y[k+h/2]=u-t;
51 w=w*wn;
52 }
53 }
54 }
55 if(on==-1)for(int i=0;i<l;i++) y[i].r/=l;
56 }
57 void init(int *a,int n,wjmzbmr *x1,int *b,int m,wjmzbmr *x2)
58 {
59 /*将a[0]~a[n-1]放到x1中,将b[0]~b[m-1]放到x2中*/
60 l=1;
61 while(l<max(n,m)*2) l<<=1;
62 for(int i=0;i<n;++i)
63 {
64 x1[i].r=a[i];
65 x1[i].i=0.0;
66 }
67 for(int i=n;i<l;++i)x1[i].r=x1[i].i=0.0;
68 for(int i=0;i<m;++i)
69 {
70 x2[i].r=b[i];
71 x2[i].i=0.0;
72 }
73 for(int i=m;i<l;i++) x2[i].r=x2[i].i=0.0;
74 }
75 int main()
76 {
77 scanf("%d %d",&n,&m);
78 ++n,++m;
79 for(int i=0;i<n;++i) scanf("%d",&a[i]);
80 for(int i=0;i<m;++i) scanf("%d",&b[i]);
81 init(a,n,x1,b,m,x2);
82 fft(x1,l,1);
83 fft(x2,l,1);
84 for(int i=0;i<l;++i) x1[i]=x1[i]*x2[i];
85 fft(x1,l,-1);
86 for(int i=0;i<n+m-1;++i) printf("%lld ",(long long)(x1[i].r+0.5));
87 return 0;
88 }
FWT

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1024,mod=1e9+7,rev=(mod+1)>>1;
4 int a[maxn+50],b[maxn+50];
5 long long fc[maxn*maxn];
6 int T,n,m;
7 void fwt(int *a,int n)
8 {
9 for(int d=1;d<n;d<<=1)
10 for(int m=d<<1,i=0;i<n;i+=m)
11 for(int j=0;j<d;j++)
12 {
13 int x=a[i+j],y=a[i+j+d];
14 a[i+j]=(x+y)%mod,a[i+j+d]=(x-y+mod)%mod;
15 //xor:a[i+j]=x+y,a[i+j+d]=(x-y+mod)%mod;
16 //and:a[i+j]=x+y;
17 //or:a[i+j+d]=x+y;
18 }
19 }
20 void ufwt(int *a,int n)
21 {
22 for(int d=1;d<n;d<<=1)
23 for(int m=d<<1,i=0;i<n;i+=m)
24 for(int j=0;j<d;j++)
25 {
26 int x=a[i+j],y=a[i+j+d];
27 a[i+j]=1LL*(x+y)*rev%mod,a[i+j+d]=(1LL*(x-y)*rev%mod+mod)%mod;
28 //xor:a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2;
29 //and:a[i+j]=x-y;
30 //or:a[i+j+d]=y-x;
31 }
32 }
33 void solve(int *a,int *b,int n)//下标0..n-1的数组a和b求异或卷积,O(nlogn),返回值在a中
34 {
35 fwt(a,n);
36 fwt(b,n);
37 for(int i=0;i<n;++i) a[i]=1LL*a[i]*b[i]%mod;
38 ufwt(a,n);
39 }
40 int main()
41 {
42 fc[0]=1;
43 for(int i=1;i<=1000000;++i) fc[i]=fc[i-1]*i%mod;
44 scanf("%d",&T);
45 while(T--)
46 {
47 scanf("%d%d",&n,&m);
48 memset(a,0,sizeof(a));
49 memset(b,0,sizeof(b));
50 for(int i=1;i<=n;++i) a[i]=1;
51 for(int i=1;i<=m;++i) b[i]=1;
52 solve(a,b,maxn);
53 long long ans=1;
54 for(int i=0;i<maxn;++i) ans=ans*fc[a[i]]%mod;
55 printf("%lld\n",ans);
56 }
57 return 0;
58 }
NTT

1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const int maxn=262144*4;
5 //const long long P=50000000001507329LL; // 190734863287 * 2 ^ 18 + 1
6 //const int P=1004535809; // 479 * 2 ^ 21 + 1
7 const ll mod=998244353; // 119 * 2 ^ 23 + 1
8 const ll G=3;
9
10 ll len=0;
11 ll pw[maxn+5],pwinv[maxn+5];
12 ll A[maxn+5],B[maxn+5];
13 ll f[maxn+5];
14 int n,m;
15
16 ll Pow(ll a,ll b,ll mod)
17 {
18 ll ans=1;
19 while(b)
20 {
21 if(b&1) ans=ans*a%mod;
22 a=a*a%mod;
23 b>>=1;
24 }
25 return ans;
26 }
27 ll Inv(ll x)
28 {
29 return Pow(x,mod-2,mod);
30 }
31 void Init()
32 {
33 ll inv=Inv(G);
34 for (int i=1;i<=maxn;i<<=1)
35 {
36 pw[i]=Pow(G,(mod-1)/i,mod);
37 pwinv[i]=Pow(inv,(mod-1)/i,mod);
38 }
39 }
40 void rader(ll *a)
41 {
42 for(int i=0,j=0;i<len;i++)
43 {
44 if(i>j) swap(a[i],a[j]);
45 int k=len;
46 do{k>>=1;j^=k;}while(j<k);
47 }
48 }
49 void ntt(ll *a,int f)
50 {
51 rader(a);
52 for(int i=2;i<=len;i<<=1)
53 {
54 int m=i>>1;
55 for(int j=0;j<len;j+=i)
56 {
57 ll w=1,wn=pw[i];
58 if(f==-1) wn=pwinv[i];
59 for(int k=0;k<m;k++)
60 {
61 ll x=a[j+k+m]*w%mod;
62 a[j+k+m]=(a[j+k]-x+mod)%mod;
63 a[j+k]=(a[j+k]+x)%mod;
64 w=w*wn%mod;
65 }
66 }
67 }
68 if(f==-1)
69 {
70 ll inv=Inv(len);
71 for(int i=0;i<len;i++) a[i]=a[i]*inv%mod;
72 }
73 }
74 void con(ll *A,int n,ll *B,int m)
75 {
76 /*A[0..n-1]与B[0..m-1]卷积*/
77 for(len=1;len<max(n,m);len<<=1);
78 len<<=1;
79 for(int i=n;i<len;++i) A[i]=0;
80 for(int i=m;i<len;++i) B[i]=0;
81 ntt(A,1);
82 ntt(B,1);
83 for(int i=0;i<len;++i) A[i]=A[i]*B[i]%mod;
84 ntt(A,-1);
85 }
86 int main()
87 {
88 Init();
89 con(A,n,B,m);
90 return 0;
91 }
Kdtree

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=500000,inf=1e9;
4 int n,m,cur,ans,root;
5 int x[maxn+50],y[maxn+50];
6 struct P
7 {
8 int mn[2],mx[2],d[2],lch,rch;
9 int& operator[](int x) {return d[x];}
10 friend bool operator<(P x,P y) {return x[cur]<y[cur];}
11 friend int dis(P x,P y) {return abs(x[0]-y[0])+abs(x[1]-y[1]);}
12 }p[maxn+50];
13 struct kdtree
14 {
15 P t[2*maxn+50],T;
16 int ans;
17 void update(int k)
18 {
19 int l=t[k].lch,r=t[k].rch;
20 for (int i=0;i<2;i++)
21 {
22 t[k].mn[i]=t[k].mx[i]=t[k][i];
23 if(l) t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]);
24 if(r) t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]);
25 if(l) t[k].mx[i]=max(t[k].mx[i],t[l].mx[i]);
26 if(r) t[k].mx[i]=max(t[k].mx[i],t[r].mx[i]);
27 }
28 }
29 int build(int l,int r,int now)
30 {
31 cur=now;
32 int mid=(l+r)/2;
33 nth_element(p+l,p+mid,p+r+1);
34 t[mid]=p[mid];
35 for(int i=0;i<2;i++) t[mid].mx[i]=t[mid].mn[i]=t[mid][i];
36 if(l<mid) t[mid].lch=build(l,mid-1,now^1);
37 if(r>mid) t[mid].rch=build(mid+1,r,now^1);
38 update(mid);
39 return mid;
40 }
41 void insert(int k,int now)
42 {
43 if(T[now]<t[k][now])
44 {
45 if(t[k].lch) insert(t[k].lch,now^1);
46 else
47 {
48 t[k].lch=++n;
49 t[n]=T;
50 for(int i=0;i<2;++i) t[n].mx[i]=t[n].mn[i]=t[n][i];
51 }
52 }
53 else
54 {
55 if(t[k].rch) insert(t[k].rch,now^1);
56 else
57 {
58 t[k].rch=++n;
59 t[n]=T;
60 for(int i=0;i<2;++i) t[n].mx[i]=t[n].mn[i]=t[n][i];
61 }
62 }
63 update(k);
64 }
65 void ins(int x,int y)
66 {
67 T[0]=x,T[1]=y;
68 T.lch=T.rch=0;
69 insert(root,0);
70 }
71 int getmn(P x)
72 {
73 int ans=0;
74 for(int i=0;i<2;i++)
75 {
76 ans+=max(T[i]-x.mx[i],0);
77 ans+=max(x.mn[i]-T[i],0);
78 }
79 return ans;
80 }//估价函数,注意如果是欧几里得距离辣么估价函数要修改
81 int getmx(P x)
82 {
83 int ans=0;
84 for(int i=0;i<2;i++) ans+=max(abs(T[i]-x.mn[i]),abs(T[i]-x.mx[i]));
85 return ans;
86 }
87 void querymx(int k)
88 {
89 ans=max(ans,dis(t[k],T));
90 int l=t[k].lch,r=t[k].rch,dl=-inf,dr=-inf;
91 if (l) dl=getmx(t[l]);
92 if (r) dr=getmx(t[r]);
93 if (dl>dr)
94 {
95 if (dl>ans) querymx(l);
96 if (dr>ans) querymx(r);
97 }
98 else
99 {
100 if (dr>ans) querymx(r);
101 if (dl>ans) querymx(l);
102 }
103 }
104 void querymn(int k)
105 {
106 //if(dis(t[k],T)) ans=min(ans,dis(t[k],T));
107 ans=min(ans,dis(t[k],T));
108 int l=t[k].lch,r=t[k].rch,dl=inf,dr=inf;
109 if(l) dl=getmn(t[l]);
110 if(r) dr=getmn(t[r]);
111 if (dl<dr)
112 {
113 if (dl<ans) querymn(l);
114 if (dr<ans) querymn(r);
115 }
116 else
117 {
118 if (dr<ans) querymn(r);
119 if (dl<ans) querymn(l);
120 }
121 }
122 int query(int f,int x,int y)
123 {
124 T[0]=x,T[1]=y;
125 T.lch=T.rch=0;
126 if (f==0) ans=-inf,querymx(root);
127 else
128 ans=inf,querymn(root);
129 return ans;
130 }
131 }kdtree;
132 int main()
133 {
134
135 scanf("%d %d",&n,&m);
136 for(int i=1;i<=n;++i)
137 {
138 scanf("%d%d",&x[i],&y[i]);
139 p[i][0]=x[i],p[i][1]=y[i];
140 }
141 root=kdtree.build(1,n,0);
142 for(int i=1;i<=m;++i)
143 {
144 int t,x,y;
145 scanf("%d %d %d",&t,&x,&y);
146 if(t==1) kdtree.ins(x,y);
147 if(t==2) printf("%d\n",kdtree.query(1,x,y));
148 }
149 return 0;
150 }
Kdtree套替罪羊

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=500000,inf=1e9;
4 int n,m,cur,ans,root;
5 int x[maxn+50],y[maxn+50];
6 struct P
7 {
8 int mn[2],mx[2],d[2],lch,rch,sz;
9 int& operator[](int x) {return d[x];}
10 friend bool operator<(P x,P y) {return x[cur]<y[cur];}
11 friend int dis(P x,P y) {return abs(x[0]-y[0])+abs(x[1]-y[1]);}
12 }p[maxn*2+50];
13 namespace kdtree
14 {
15 const double alpha=0.75;
16 P t[2*maxn+50],T;
17 int id[maxn+5];
18 int ans,len,tot;
19 bool cmp(const int x,const int y)
20 {
21 return p[x][cur]<p[y][cur];
22 }
23 void update(int k)
24 {
25 int l=t[k].lch,r=t[k].rch;
26 t[k].sz=t[t[k].lch].sz+t[t[k].rch].sz+1;
27 for (int i=0;i<2;i++)
28 {
29 t[k].mn[i]=t[k].mx[i]=t[k][i];
30 if(l) t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]);
31 if(r) t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]);
32 if(l) t[k].mx[i]=max(t[k].mx[i],t[l].mx[i]);
33 if(r) t[k].mx[i]=max(t[k].mx[i],t[r].mx[i]);
34 }
35 }
36 int build(int l,int r,int now)
37 {
38 if(l>r) return 0;
39 cur=now;
40 int mid=(l+r)/2;
41 nth_element(id+l,id+mid,id+r+1,cmp);
42 int k=id[mid];
43 t[k]=p[k];
44 t[k].sz=1,t[k].lch=t[k].rch=0;
45 for(int i=0;i<2;i++) t[k].mx[i]=t[k].mn[i]=t[k][i];
46 if(l<mid) t[k].lch=build(l,mid-1,now^1);
47 if(r>mid) t[k].rch=build(mid+1,r,now^1);
48 update(k);
49 return k;
50 }
51 void getid(int k)
52 {
53 id[++tot]=k;
54 p[k]=t[k];
55 if(t[k].lch) getid(t[k].lch);
56 if(t[k].rch) getid(t[k].rch);
57 }
58 int rebuild(int k,int now)
59 {
60 tot=0;
61 getid(k);
62 return build(1,tot,now);
63 }
64 int insert(int k,int now)
65 {
66 if(T[now]<t[k][now])
67 {
68 if(t[k].lch) t[k].lch=insert(t[k].lch,now^1);
69 else
70 {
71 t[k].lch=++len;
72 t[len]=T;
73 for(int i=0;i<2;++i) t[len].mx[i]=t[len].mn[i]=t[len][i];
74 }
75 }
76 else
77 {
78 if(t[k].rch) t[k].rch=insert(t[k].rch,now^1);
79 else
80 {
81 t[k].rch=++len;
82 t[len]=T;
83 for(int i=0;i<2;++i) t[len].mx[i]=t[len].mn[i]=t[len][i];
84 }
85 }
86 update(k);
87 if(t[k].sz*alpha+3<max(t[t[k].lch].sz,t[t[k].rch].sz)) k=rebuild(k,now);
88 return k;
89 }
90 void ins(int x,int y)
91 {
92 T[0]=x,T[1]=y;
93 T.sz=1;
94 T.lch=T.rch=0;
95 if(root==0)
96 {
97 len=1;
98 t[len]=T;
99 update(len);
100 root=len;
101 return;
102 }
103 root=insert(root,0);
104 }
105 int getmn(P x)
106 {
107 int ans=0;
108 for(int i=0;i<2;i++)
109 {
110 ans+=max(T[i]-x.mx[i],0);
111 ans+=max(x.mn[i]-T[i],0);
112 }
113 return ans;
114 }//估价函数,注意如果是欧几里得距离辣么估价函数要修改
115 int getmx(P x)
116 {
117 int ans=0;
118 for(int i=0;i<2;i++) ans+=max(abs(T[i]-x.mn[i]),abs(T[i]-x.mx[i]));
119 return ans;
120 }
121 void querymx(int k)
122 {
123 ans=max(ans,dis(t[k],T));
124 int l=t[k].lch,r=t[k].rch,dl=-inf,dr=-inf;
125 if (l) dl=getmx(t[l]);
126 if (r) dr=getmx(t[r]);
127 if (dl>dr)
128 {
129 if (dl>ans) querymx(l);
130 if (dr>ans) querymx(r);
131 }
132 else
133 {
134 if (dr>ans) querymx(r);
135 if (dl>ans) querymx(l);
136 }
137 }
138 void querymn(int k)
139 {
140 //if(dis(t[k],T)) ans=min(ans,dis(t[k],T));
141 ans=min(ans,dis(t[k],T));
142 int l=t[k].lch,r=t[k].rch,dl=inf,dr=inf;
143 if(l) dl=getmn(t[l]);
144 if(r) dr=getmn(t[r]);
145 if (dl<dr)
146 {
147 if (dl<ans) querymn(l);
148 if (dr<ans) querymn(r);
149 }
150 else
151 {
152 if (dr<ans) querymn(r);
153 if (dl<ans) querymn(l);
154 }
155 }
156 int query(int f,int x,int y)
157 {
158 T[0]=x,T[1]=y;
159 T.lch=T.rch=0;
160 if (f==0) ans=-inf,querymx(root);
161 else
162 ans=inf,querymn(root);
163 return ans;
164 }
165 }
166 int main()
167 {
168 read(n);
169 read(m);
170 for(int i=1;i<=n;++i)
171 {
172 read(x[i]);
173 read(y[i]);
174 p[i][0]=x[i],p[i][1]=y[i];
175 }
176 kdtree::len=n;
177 for(int i=1;i<=n;++i) kdtree::id[i]=i;
178 root=kdtree::build(1,n,0);
179 for(int i=1;i<=m;++i)
180 {
181 int t,x,y;
182 read(t);
183 read(x);
184 read(y);
185 if(t==1) kdtree::ins(x,y);
186 if(t==2) printf("%d\n",kdtree::query(1,x,y));
187 }
188 return 0;
189 }
左偏树

1 //APIO2012 dispatching
2 #include<bits/stdc++.h>
3 using namespace std;
4 const int maxn=1e5;
5 vector<int> g[maxn+50];
6 long long cost[maxn+50],lead[maxn+50],sum[maxn+50],num[maxn+50];
7 int l[maxn+50],r[maxn+50],dist[maxn+50];
8 int n,m,root;
9 long long ans=0;
10 int merge(int u,int v)//左偏树核心操作——merge:合并两个左偏树
11 {
12 if(!u) return v;
13 if(!v) return u;
14 if(cost[u]<cost[v]) swap(u,v);//此处是大根堆
15 r[u]=merge(r[u],v);
16 if(dist[r[u]]>dist[l[u]]) swap(l[u],r[u]);//时刻保证dist(l)>=dist(r)
17 if(r[u]) dist[u]=dist[r[u]]+1;else dist[u]=0;//更新dist数组
18 num[u]=num[l[u]]+num[r[u]]+1;
19 sum[u]=sum[l[u]]+sum[r[u]]+cost[u];//维护节点信息
20 return u;
21 }
22 int del(int u)
23 {
24 return merge(l[u],r[u]);//删除操作就是去掉根节点,merge左右儿子
25 }
26 int dfs(int k)
27 {
28 int u=k;
29 num[u]=1,sum[u]=cost[u];
30 while(sum[u]>m) u=del(u);
31 for(int i=0;i<g[k].size();++i)
32 {
33 int v=dfs(g[k][i]);
34 u=merge(u,v);
35 while(sum[u]>m) u=del(u);
36 }
37 ans=max(ans,lead[k]*num[u]);
38 return u;
39 }
40 int main()
41 {
42 scanf("%d%d",&n,&m);
43 for(int i=1;i<=n;++i) g[i].clear();
44 for(int i=1;i<=n;++i)
45 {
46 int x;
47 scanf("%d%d%d",&x,&cost[i],&lead[i]);
48 if(lead[i]==0) root=i;
49 g[x].push_back(i);
50 }
51 memset(l,0,sizeof(l));
52 memset(r,0,sizeof(r));
53 memset(dist,0,sizeof(dist));
54 memset(sum,0,sizeof(sum));
55 memset(num,0,sizeof(num));
56 dfs(1);
57 printf("%lld",ans);
58 return 0;
59 }
莫比乌斯反演(筛积性函数+分块求和)

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1e5;
4 int mu[maxn+50],prime[maxn+50],sum[maxn+50];
5 bool f[maxn+50];
6 int a,b,c,d,k;
7 long long solve(int n,int m)
8 {
9 if(n>m) swap(n,m);
10 long long ans=0;
11 for(int i=1,la=0;i<=n;i=la+1)
12 {
13 la=min(n/(n/i),m/(m/i));
14 ans+=(long long)(sum[la]-sum[i-1])*(n/i)*(m/i);
15 }//对于n/i * m/i 采用分块求和的根号n+根号m的做法
16 return ans;
17 }
18 int main()
19 {
20 mu[1]=1;
21 memset(f,0,sizeof(f));
22 f[1]=1;
23 for(int i=2;i<=maxn;++i)
24 {
25 if(!f[i])
26 {
27 prime[++prime[0]]=i;
28 mu[i]=-1;
29 }
30 for(int j=1;j<=prime[0];++j)
31 {
32 if(i*prime[j]>maxn) break;
33 f[i*prime[j]]=1;
34 if(i%prime[j]==0)
35 {
36 mu[i*prime[j]]=0;
37 break;
38 }
39 else mu[i*prime[j]]=-mu[i];
40 }
41 }//筛积性函数
42 memset(sum,0,sizeof(sum));
43 sum[1]=mu[1];
44 for(int i=2;i<=maxn;++i) sum[i]=sum[i-1]+mu[i];
45 int T;
46 scanf("%d",&T);
47 for(int cas=1;cas<=T;++cas)
48 {
49 printf("Case %d: ",cas);
50 scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
51 if(k==0) printf("0\n");else
52 {
53 long long ans=solve(b/k,d/k)-solve((a-1)/k,d/k)-solve(b/k,(c-1)/k)+solve((a-1)/k,(c-1)/k);
54 a=max(a,c),b=min(b,d);
55 long long ans1=solve(b/k,b/k)-solve((a-1)/k,b/k)-solve(b/k,(a-1)/k)+solve((a-1)/k,(a-1)/k);
56 printf("%lld\n",ans-ans1/2);
57 }
58 }
59 return 0;
60 }
插头dp(最小表示法实现)

1 /*
2 Ural 1519
3 */
4 #include<bits/stdc++.h>
5 using namespace std;
6 const int maxn=12,maxs=1e6,mod=30007;
7 struct wjmzbmr
8 {
9 vector<long long> hash[mod];
10 vector<int> num[mod];//num记录状态的编号
11 int len;
12 long long f[maxs],state[maxs];//f存的是该编号状态的dp值,state存的是该编号状态的数字
13 void init()
14 {
15 len=0;
16 for(int i=0;i<mod;++i) hash[i].clear(),num[i].clear();
17 }
18 void push(long long s,long long x)//把s状态的dp值加上x
19 {
20 int v=s%mod;
21 for(int i=0;i<hash[v].size();++i)
22 if(hash[v][i]==s)
23 {
24 f[num[v][i]]+=x;
25 return;
26 }
27 ++len;
28 hash[v].push_back(s);
29 num[v].push_back(len);
30 state[len]=s,f[len]=x;
31 }
32 }Hash[2];
33 int maze[maxn+5][maxn+5];
34 char s[maxn+5];
35 int code[maxn+5];
36 int n,m,cur,ex=0,ey=0;
37 void decode(int *code,long long s)//解码,将状态s存到数组中,此题是8进制
38 {
39 for(int i=m;i>=0;--i)
40 {
41 code[i]=s&7;
42 s>>=3;
43 }
44 }
45 long long encode(int *code)//编码,顺带用最小表示法更新标号
46 {
47 int color[maxn+5],cnt=0;
48 long long s=0;
49 memset(color,-1,sizeof(color));
50 color[0]=0;
51 for(int i=0;i<=m;++i)
52 {
53 if(color[code[i]]==-1) color[code[i]]=++cnt;
54 code[i]=color[code[i]];
55 s<<=3;
56 s|=code[i];
57 }
58 return s;
59 }
60 void shift(int *code)//当轮廓线移到最后一列的时候需要特殊处理
61 {
62 for(int i=m;i>0;--i) code[i]=code[i-1];
63 code[0]=0;
64 }
65 void dpblank(int x,int y)
66 {
67 int left,up;
68 for(int i=1;i<=Hash[cur].len;++i)
69 {
70 decode(code,Hash[cur].state[i]);
71 left=code[y-1],up=code[y];
72 if(left&&up)//第一种情况,left和up都存在,(i,j)的作用是合并两个连通分量
73 {
74 if(left==up)//此题的特殊情况,连成一个整环只允许在最后一个非障碍格子
75 {
76 if(x==ex&&y==ey)
77 {
78 code[y]=code[y-1]=0;
79 if(y==m) shift(code);
80 Hash[cur^1].push(encode(code),Hash[cur].f[i]);
81 }
82 }
83 else//合并两个连通分量
84 {
85 for(int i=0;i<=m;++i)
86 if(code[i]==up) code[i]=left;
87 code[y]=code[y-1]=0;
88 if(y==m) shift(code);
89 Hash[cur^1].push(encode(code),Hash[cur].f[i]);
90 }
91 }
92 else
93 if(left||up)//枚举(i,j)放右插头还是下插头
94 {
95 int t;
96 if(left) t=left;else t=up;
97 if(maze[x][y+1])
98 {
99 code[y-1]=0,code[y]=t;
100 Hash[cur^1].push(encode(code),Hash[cur].f[i]);
101 }
102 if(maze[x+1][y])
103 {
104 code[y-1]=t,code[y]=0;
105 if(y==m) shift(code);
106 Hash[cur^1].push(encode(code),Hash[cur].f[i]);
107 }
108 }
109 else
110 if(maze[x+1][y]&&maze[x][y+1])//该格子没有左插头也没有上插头,此题自己不能为空,所以它只有自己成一个新连通分量
111 {
112 code[y-1]=code[y]=8;//只需要填一个没有出现过的数即可,在最小表示法的时候会修正这个值
113 if(y==m) shift(code);
114 Hash[cur^1].push(encode(code),Hash[cur].f[i]);
115 }
116 }
117 }
118 void dpblock(int x,int y)
119 {
120 for(int i=1;i<=Hash[cur].len;++i)//当(x,y)是障碍格子的时候,肯定没有下插头、右插头
121 {
122 decode(code,Hash[cur].state[i]);
123 code[y-1]=code[y]=0;
124 if(y==m) shift(code);
125 Hash[cur^1].push(encode(code),Hash[cur].f[i]);
126 }
127 }
128 int main()
129 {
130 scanf("%d%d",&n,&m);
131 for(int i=1;i<=n;++i)
132 {
133 scanf("%s",s+1);
134 for(int j=1;j<=m;++j)
135 if(s[j]=='.') maze[i][j]=1,ex=i,ey=j;
136 }
137 Hash[cur=0].init();
138 Hash[cur].push(0,1);
139 for(int i=1;i<=n;++i)
140 for(int j=1;j<=m;++j)
141 {
142 Hash[cur^1].init();
143 if(maze[i][j]) dpblank(i,j);else dpblock(i,j);
144 cur^=1;
145 }
146 long long ans=0;
147 for(int i=1;i<=Hash[cur].len;++i) ans+=Hash[cur].f[i];//最后的cur中存的状态都是能转移到的合法状态
148 printf("%lld\n",ans);
149 return 0;
150 }
SAM(后缀自动机)

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1e6;
4 char s[maxn+5];
5 int sz=0,len,last=0;
6 int maxlen[2*maxn+50],minlen[2*maxn+50],trans[2*maxn+50][26],slink[2*maxn+50],endpos[2*maxn+50],d[maxn*2+50];
7 long long ans[maxn*2+50];
8 int suf[maxn+5];
9 int g[maxn+5][26];
10 bool p[maxn*2+50];
11 bool vis[maxn*2+5];
12 queue<int> q;
13 int build(int _maxlen,int _minlen,int* _trans,int _slink)
14 {
15 maxlen[++sz]=_maxlen;
16 minlen[sz]=_minlen;
17 for(int i=0;i<26;++i)
18 if(_trans==NULL) trans[sz][i]=-1;else trans[sz][i]=_trans[i];
19 slink[sz]=_slink;
20 ++d[_slink];
21 return sz;
22 }
23 int add(char ch,int u)
24 {
25 int c=ch-'a';
26 int z=build(maxlen[u]+1,-1,NULL,-1);
27 p[z]=1;
28 int v=u;
29 while(v!=-1&&trans[v][c]==-1) trans[v][c]=z,v=slink[v];
30 if(v==-1)//最简单的情况,suffix-path(u->S)上都没有对应字符ch的转移
31 {
32 minlen[z]=1;
33 slink[z]=0;
34 ++d[0];
35 return z;
36 }
37 int x=trans[v][c];
38 if(maxlen[v]+1==maxlen[x])//较简单的情况,不用拆分x
39 {
40 minlen[z]=maxlen[x]+1;
41 slink[z]=x;
42 ++d[x];
43 return z;
44 }
45 int y=build(maxlen[v]+1,-1,trans[x],slink[x]); //最复杂的情况,拆分x,y表示<=maxlen[v]+1的那段
46 slink[y]=slink[x];
47 --d[slink[x]];
48 minlen[x]=maxlen[y]+1;
49 slink[x]=y;
50 ++d[y];
51 minlen[z]=maxlen[y]+1;
52 slink[z]=y;
53 ++d[y];
54 int w=v;
55 while(w!=-1&&trans[w][c]==x) trans[w][c]=y,w=slink[w];
56 minlen[y]=maxlen[slink[y]]+1;
57 return z;
58 }
59 void addedge(int u,int v,int w)
60 {
61 g[u][w]=v;
62 }
63 void goup(int k,int start,int step)
64 {
65 if(k==0||vis[k]) return;
66 vis[k]=1;
67 int father=slink[k];
68 step-=maxlen[k]-minlen[k]+1;
69 addedge(father,k,s[start+step]-'a');
70 goup(father,start,step);
71 }
72 int main()
73 {
74 int T;
75 scanf("%d",&T);
76 while(T--)
77 {
78 scanf("%s",s);
79 len=strlen(s);
80 for(int i=0;i<=2*len;++i)
81 {
82 for(int j=0;j<26;++j) trans[i][j]=-1;
83 slink[i]=-1;
84 maxlen[i]=minlen[i]=0;
85 memset(g[i],0,sizeof(g[i]));
86 suf[i]=-1;
87 //memset(limit[i],0,sizeof(limit[i]));
88 //dp[i]=0;
89 }
90 for(int i=0;i<26;++i) trans[0][i]=slink[0]=-1;
91 maxlen[0]=minlen[0]=0;
92 sz=0;
93 last=0;
94 for(int i=0;i<len;++i)
95 {
96 last=add(s[i],last);//后缀树要倒过来建
97 suf[last]=i;
98 }
99 memset(endpos,0,sizeof(endpos));
100 while(!q.empty()) q.pop();
101 for(int i=1;i<=sz;++i) if(d[i]==0) q.push(i);
102
103 for(int i=0;i<=sz;++i) vis[i]=0;
104 for(int i=1;i<=sz;++i)
105 if(suf[i]!=-1) goup(i,suf[i],len-suf[i]);
106
107 while(!q.empty())
108 {
109 int u=q.front();
110 q.pop();
111 if(p[u]) ++endpos[u];
112 endpos[slink[u]]+=endpos[u];
113 if(--d[slink[u]]==0&&slink[u]!=0) q.push(slink[u]);
114 }
115 memset(ans,0,sizeof(ans));
116 for(int i=1;i<=sz;++i) ans[maxlen[i]]=max(ans[maxlen[i]],(long long)endpos[i]);
117 for(int i=len-1;i>=1;--i) ans[i]=max(ans[i],ans[i+1]);
118 for(int i=1;i<=len;++i) printf("%lld\n",ans[i]);
119 }
120 return 0;
121 }
图的遍历(非递归)

1 void dfs(int k,int last)
2 {
3 /* L[k]=++t;
4 deep[k]=deep[last]+1;
5 fa[k][0]=last;
6 for(int i=0;i<g[k].size();++i)
7 if(g[k][i]!=last) dfs(g[k][i],k);
8 R[k]=t;*/
9 while(!s.empty()) s.pop();
10 memset(head,0,sizeof(head));//head[i]表示第i个点当前遍历到了第几个相邻点
11 s.push(0);
12 s.push(1);
13 while(s.size()>1)
14 {
15 int k=s.top();
16 s.pop();
17 int last=s.top();
18 s.push(k);
19 if(!head[k])
20 {
21 L[k]=++t;
22 deep[k]=deep[last]+1;
23 fa[k][0]=last;
24 }
25 if(head[k]<g[k].size())
26 if(g[k][head[k]]==last) ++head[k];
27 if(head[k]==g[k].size())
28 {
29 R[k]=t;
30 s.pop();
31 }
32 else
33 s.push(g[k][head[k]++]);
34 }
35 }
cdq分治模板(三维偏序)

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1e5;
4 struct wjmzbmr
5 {
6 int x,y,z,id;
7 };
8 wjmzbmr a[maxn+50],p[maxn+50];
9 bool cmp(wjmzbmr a,wjmzbmr b)
10 {
11 if(a.x!=b.x) return a.x<b.x;
12 if(a.y!=b.y) return a.y<b.y;
13 return a.z<b.z;
14 }
15 bool cmp2(wjmzbmr a,wjmzbmr b)
16 {
17 if(a.y!=b.y) return a.y<b.y;
18 return a.z<b.z;
19 }
20 int c[maxn+50],ans[maxn+50];
21 int n,maxz;
22 int lowbit(int x)
23 {
24 return x&(-x);
25 }
26 void add(int k,int num)
27 {
28 for(int i=k;i<=maxz;i+=lowbit(i)) c[i]+=num;
29 }
30 int query(int k)
31 {
32 int ans=0;
33 for(int i=k;i;i-=lowbit(i)) ans+=c[i];
34 return ans;
35 }
36 void cdq(int l,int r)
37 {
38 if(l==r) return;
39 int mid=(l+r)>>1;
40 cdq(l,mid);
41 for(int i=l;i<=r;++i) p[i]=a[i];
42 //cdq(mid+1,r);
43 sort(p+l,p+mid+1,cmp2);
44 sort(p+mid+1,p+r+1,cmp2);
45 int i=l;
46 for(int j=mid+1;j<=r;++j)
47 {
48 while(i<=mid&&p[i].y<=p[j].y) add(p[i].z,1),++i;
49 ans[p[j].id]+=query(p[j].z);
50 }
51 for(int j=l;j<i;++j) add(p[j].z,-1);
52 cdq(mid+1,r);
53 }
54 int main()
55 {
56 int T;
57 scanf("%d",&T);
58 while(T--)
59 {
60 scanf("%d",&n);
61 maxz=0;
62 for(int i=1;i<=n;++i) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z),a[i].id=i,maxz=max(maxz,a[i].z);
63 sort(a+1,a+n+1,cmp);
64 memset(c,0,sizeof(c));
65 memset(ans,0,sizeof(ans));
66 cdq(1,n);
67 for(int i=n-1;i>=1;--i)
68 if(a[i].x==a[i+1].x&&a[i].y==a[i+1].y&&a[i].z==a[i+1].z) ans[a[i].id]=ans[a[i+1].id];
69 for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
70 }
71 return 0;
72 }
优先队列

1 struct priorityqueue
2 {
3 int num[maxn+50],t[maxn+50];//num表示数字,t表示时间
4 int l,r;
5 void init()
6 {
7 l=1;
8 r=0;
9 }
10 void push(int nu,int tu)//插入一个数字为nu,时间为tu的元素
11 {
12 while(r>=l&&num[r]>=nu) --r;
13 ++r;
14 num[r]=nu,t[r]=tu;
15 }
16 void pop(int tu)//删除时间<tu的元素
17 {
18 while(l<=r&&t[l]<tu) ++l;
19 }
20 int getmin()//得到最小值
21 {
22 if(l>r) return inf;
23 else
24 return num[l];
25 }
26 };
手写bitset

1 struct Bitset
2 {
3 /*32位压成一个unsigned int,最多压8个*/
4 unsigned int a[8];
5 void clear()
6 {
7 for(int i=0;i<8;++i) a[i]=0;
8 }
9 void set(int x)
10 {
11 /*第x位置1*/
12 a[x>>5]|=1U<<(x&31);
13 /*
14 x>>5即x/32,确定x在哪个数组里
15 x&31即x%32,确定x在对应数组里的第几小位
16 */
17 }
18 void flip(int x)
19 {
20 /*将第x位反转*/
21 a[x>>5]^=1U<<(x&31);
22 }
23 int get(int x)
24 {
25 /*返回第x位的值0/1*/
26 return a[x>>5]&(1U<<(x&31));
27 }
28 }num;
29 //手写bitset的强大之处就是可以快速取出所有是1的位置,不过其实bitset里也封装了_Find_first()和_Find_next(x)
30 for(int i=0;i<8;++i)
31 {
32 while(true)
33 {
34 if(!num.a[i]) break;
35 int p=__builtin_ctz(num.a[i]);//__builtin_ctz(unsigned int x) 是通过O(1)的时间返回数字x最右边连续0的个数
36 printf("%d\n",i<<5|p);
37 num.flip(i<<5|p);
38 }
39 }
40 //手写bitset还可以取出连续的一段区间,但是封装的却不行
41 void make(int l,int r)
42 {
43 int shift=l&31;
44 int y=(r-l)>>5;
45 int j=l>>5;
46 for(int i=0;i<y;++i)
47 {
48 u num=(a.num[j]>>shift);
49 if(shift!=0) num|=a.num[j+1]<<(32-shift);//注意x<<32并不是0,而是x本身
50 ans.num[i]^=num;
51 ++j;
52 }
53 for(int i=l+32*y;i<=r;++i)
54 if(a.get(i))
55 ans.flip(i-l);
56 }
决策单调性优化

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=200,inf=1e7;
4 int a[maxn+50],f[maxn+50][50+5];
5 int kk[maxn+50][50+5];
6 int m,s,n;
7 struct wjmzbmr
8 {
9 int l,r,p;
10 }q[maxn+50];
11 int cal(int j,int i,int p)
12 {
13 return f[p][j]+a[i]-a[p+1]+1;
14 }
15 int find(int j,int l,int r,int p,int pp)
16 {
17 int mid;
18 bool flag=0;
19 while(l<r)
20 {
21 mid=(l+r)>>1;
22 if(cal(j-1,mid,p)>cal(j-1,mid,pp)) l=mid+1;else r=mid;
23 }
24 if(cal(j-1,r,p)<cal(j-1,r,pp)) return r;else return r+1;
25 }
26 int main()
27 {
28 scanf("%d%d%d",&m,&s,&n);
29 for(int i=1;i<=n;++i) scanf("%d",&a[i]);
30 sort(a+1,a+n+1);
31 for(int i=0;i<=n;++i)
32 for(int j=0;j<=m;++j)
33 f[i][j]=inf;
34 memset(f[0],0,sizeof(f[0]));
35 for(int i=1;i<=n;++i) f[i][1]=a[i]-a[1]+1;
36 for(int j=2;j<=m;++j)
37 {
38 int head=1,tail=1;
39 q[1]={1,n,0};
40 for(int i=1;i<=n;++i)
41 {
42 while(head<tail&&q[head].r<i) ++head;
43 f[i][j]=cal(j-1,i,q[head].p);
44 while(head<tail&&cal(j-1,q[tail].l,i)<cal(j-1,q[tail].l,q[tail].p)) --tail;
45 int position=find(j,q[tail].l,q[tail].r,i,q[tail].p);
46 if(position<=n)
47 {
48 q[tail+1]={position,n,i};
49 q[tail].r=position-1;
50 if(q[tail].l>q[tail].r) ++head;
51 ++tail;
52 }
53 }
54 }
55 printf("%d\n",f[n][m]);
56 return 0;
57 }
Berlekamp-Massey算法

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define rep(i,a,n) for (int i=a;i<n;i++)
4 #define per(i,a,n) for (int i=n-1;i>=a;i--)
5 #define pb push_back
6 #define mp make_pair
7 #define all(x) (x).begin(),(x).end()
8 #define fi first
9 #define se second
10 #define SZ(x) ((int)(x).size())
11 typedef vector<int> VI;
12 typedef long long ll;
13 typedef pair<int,int> PII;
14 const ll mod=1000000007;
15 ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
16 // head
17
18 ll n;
19 namespace linear_seq {
20 const int N=10010;
21 ll res[N],base[N],_c[N],_md[N];
22
23 vector<int> Md;
24 void mul(ll *a,ll *b,int k) {
25 rep(i,0,k+k) _c[i]=0;
26 rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod;
27 for (int i=k+k-1;i>=k;i--) if (_c[i])
28 rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod;
29 rep(i,0,k) a[i]=_c[i];
30 }
31 int solve(ll n,VI a,VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
32 // printf("%d\n",SZ(b));
33 ll ans=0,pnt=0;
34 int k=SZ(a);
35 assert(SZ(a)==SZ(b));
36 rep(i,0,k) _md[k-1-i]=-a[i];_md[k]=1;
37 Md.clear();
38 rep(i,0,k) if (_md[i]!=0) Md.push_back(i);
39 rep(i,0,k) res[i]=base[i]=0;
40 res[0]=1;
41 while ((1ll<<pnt)<=n) pnt++;
42 for (int p=pnt;p>=0;p--) {
43 mul(res,res,k);
44 if ((n>>p)&1) {
45 for (int i=k-1;i>=0;i--) res[i+1]=res[i];res[0]=0;
46 rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod;
47 }
48 }
49 rep(i,0,k) ans=(ans+res[i]*b[i])%mod;
50 if (ans<0) ans+=mod;
51 return ans;
52 }
53 VI BM(VI s) {
54 VI C(1,1),B(1,1);
55 int L=0,m=1,b=1;
56 rep(n,0,SZ(s)) {
57 ll d=0;
58 rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod;
59 if (d==0) ++m;
60 else if (2*L<=n) {
61 VI T=C;
62 ll c=mod-d*powmod(b,mod-2)%mod;
63 while (SZ(C)<SZ(B)+m) C.pb(0);
64 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
65 L=n+1-L; B=T; b=d; m=1;
66 } else {
67 ll c=mod-d*powmod(b,mod-2)%mod;
68 while (SZ(C)<SZ(B)+m) C.pb(0);
69 rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod;
70 ++m;
71 }
72 }
73 return C;
74 }
75 int gao(VI a,ll n) {
76 VI c=BM(a);
77 c.erase(c.begin());
78 rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod;
79 return solve(n,c,VI(a.begin(),a.begin()+SZ(c)));
80 }
81 };
82 vector<int> a;
83 int main() {
84 int T;
85 scanf("%d",&T);
86 a.clear();
87 a.pb(31),a.pb(197),a.pb(1255),a.pb(7997),a.pb(50959),a.pb(324725);
88 while(T--)
89 {
90 scanf("%lld",&n);
91 printf("%d\n",linear_seq::gao(a,n-1));
92 }
93 return 0;
94 }
FastIO

1 typedef long long LL;
2 namespace fastIO {
3 #define BUF_SIZE 100000
4 //fread -> read
5 bool IOerror = 0;
6 inline char nc() {
7 static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
8 if(p1 == pend) {
9 p1 = buf;
10 pend = buf + fread(buf, 1, BUF_SIZE, stdin);
11 if(pend == p1) {
12 IOerror = 1;
13 return -1;
14 }
15 }
16 return *p1++;
17 }
18 inline bool blank(char ch) {
19 return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
20 }
21 inline void read(int &x) {
22 char ch;
23 while(blank(ch = nc()));
24 if(IOerror)
25 return;
26 for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
27 }
28 #undef BUF_SIZE
29 };
30 using namespace fastIO;
虚树

1 void buildtree()
2 {
3 len=0;
4 sort(a+1,a+m+1,cmp);//关键点
5 id.clear();//记录出现的关键点
6 id.push_back(a[1]);
7 s[++len]=a[1];
8 for(int i=2;i<=m;i++)
9 {
10 int x=a[i],f=lca(s[len],x);
11 while(deep[f]<deep[s[len]])
12 {
13 if(deep[f]>=deep[s[len-1]])
14 {
15 addedge(f,s[len],abs(deep[f]-deep[s[len]]));//虚树addedge(u,v,w)
16 len--;
17 if(f!=s[len]) s[++len]=f;
18 break;
19 }
20 addedge(s[len-1],s[len],abs(deep[s[len-1]]-deep[s[len]]));
21 len--;
22 }
23 if(s[len]!= x) s[++len]=x;
24 }
25 while(--len) addedge(s[len],s[len+1],abs(deep[s[len+1]]-deep[s[len]]));
26 }
单纯形法(uva10498)

#include<bits/stdc++.h>
using namespace std;
const int maxm = 500; // 约束数目上限
const int maxn = 500; // 变量数目上限
const double INF = 1e100;
const double eps = 1e-10;
struct Simplex
{
int n; // 变量个数
int m; // 约束个数
double a[maxm][maxn]; // 输入矩阵
int B[maxm], N[maxn]; // 算法辅助变量
void pivot(int r, int c)
{
swap(N[c], B[r]);
a[r][c] = 1 / a[r][c];
for(int j = 0; j <= n; j++)
if(j != c) a[r][j] *= a[r][c];
for(int i = 0; i <= m; i++)
if(i != r)
{
for(int j = 0; j <= n; j++)
if(j != c) a[i][j] -= a[i][c] * a[r][j];
a[i][c] = -a[i][c] * a[r][c];
}
}
bool feasible()
{
for(;;)
{
int r, c;
double p = INF;
for(int i = 0; i < m; i++) if(a[i][n] < p) p = a[r = i][n];
if(p > -eps) return true;
p = 0;
for(int i = 0; i < n; i++) if(a[r][i] < p) p = a[r][c = i];
if(p > -eps) return false;
p = a[r][n] / a[r][c];
for(int i = r+1; i < m; i++)
if(a[i][c] > eps)
{
double v = a[i][n] / a[i][c];
if(v < p) { r = i; p = v; }
}
pivot(r, c);
}
}
// 解有界返回1,无解返回0,无界返回-1。b[i]为x[i]的值,ret为目标函数的值
int simplex(int n, int m, double x[maxn], double& ret)
{
this->n = n;
this->m = m;
for(int i = 0; i < n; i++) N[i] = i;
for(int i = 0; i < m; i++) B[i] = n+i;
if(!feasible()) return 0;
for(;;)
{
int r, c;
double p = 0;
for(int i = 0; i < n; i++) if(a[m][i] > p) p = a[m][c = i];
if(p < eps)
{
for(int i = 0; i < n; i++) if(N[i] < n) x[N[i]] = 0;
for(int i = 0; i < m; i++) if(B[i] < n) x[B[i]] = a[i][n];
ret = -a[m][n];
return 1;
}
p = INF;
for(int i = 0; i < m; i++) if(a[i][c] > eps)
{
double v = a[i][n] / a[i][c];
if(v < p) { r = i; p = v; }
}
if(p == INF) return -1;
pivot(r, c);
}
}
};
//////////////// 题目相关
Simplex solver;
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) == 2)
{
for(int i = 0; i < n; i++) scanf("%lf", &solver.a[m][i]); // 目标函数
solver.a[m][n] = 0; // 目标函数常数项
for(int i = 0; i < m; i++)
for(int j = 0; j < n+1; j++)
scanf("%lf", &solver.a[i][j]);
double ans, x[maxn];
assert(solver.simplex(n, m, x, ans) == 1);
ans *= m;
printf("Nasa can spend %d taka.\n", (int)floor(ans + 1 - eps));
}
return 0;
}
Split-Merge Treap(fhq treap/非旋转式treap)

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1e5,inf=1e9,mod=1e6;
4 int pre[maxn+5],ch[maxn+5][2],val[maxn+5],key[maxn+5];
5 int n,root,len;
6 int Rand()
7 {
8 int ans=0;
9 for(int i=1;i<=8;++i) ans=ans*10+rand()%10;
10 return ans;
11 }
12 void split(int k,int x,int &u,int &v)
13 {
14 if(!k) u=v=0;
15 else
16 {
17 pushdown(k);
18 if(x<=sz[ch[k][0]]) v=k,split(ch[k][0],x,u,ch[k][0]);
19 else u=k,split(ch[k][1],x-sz[ch[k][0]]-1,ch[k][1],v);
20 /* if(val[k]<=x) u=k,split(ch[k][1],x,ch[k][1],v);
21 else v=k,split(ch[k][0],x,u,ch[k][0]); */
22 update(k);
23 }
24 }
25 int merge(int u,int v)
26 {
27 /*
28 将两个子树u,v合并,其中u子树的权值都小于v子树
29 */
30 if(!u) return v;
31 if(!v) return u;
32 pushdown(u),pushdown(v);
33 if(key[u]<key[v])
34 {
35 ch[u][1]=merge(ch[u][1],v);
36 update(u);
37 return u;
38 }
39 else
40 {
41 ch[v][0]=merge(u,ch[v][0]);
42 update(v);
43 return v;
44 }
45 }
46 int newnode(int x)
47 {
48 /*
49 新建一个权值为x的结点
50 */
51 ++len;
52 val[len]=x;
53 ch[len][0]=ch[len][1]=0;
54 key[len]=Rand()%1000000000;
55 return len;
56 }
57 void insert(int x)
58 {
59 /*
60 插入一个权值为x的结点
61 */
62 int u,v;
63 split(root,x,u,v);
64 root=merge(merge(u,newnode(x)),v);
65 }
66 void del(int x)
67 {
68 /*
69 删除一个权值为x的结点
70 */
71 int u,v,c,d;
72 split(root,x,u,v);
73 split(u,x-1,c,d);
74 d=merge(ch[d][0],ch[d][1]);
75 u=merge(c,d);
76 root=merge(u,v);
77 }
78 int getpre(int k,int x)
79 {
80 /*
81 从以k为根的子树中找到x的前驱
82 */
83 if(!k) return -inf;
84 if(x==val[k]) return x;
85 if(x<val[k]) return getpre(ch[k][0],x);
86 return max(val[k],getpre(ch[k][1],x));
87 }
88 int getsuf(int k,int x)
89 {
90 /*
91 从以k为根的子树中找到x的后继
92 */
93 if(!k) return inf;
94 if(x==val[k]) return x;
95 if(x>val[k]) return getsuf(ch[k][1],x);
96 return min(val[k],getsuf(ch[k][0],x));
97 }
98 int main()
99 {
100 srand(time(0));
101 scanf("%d",&n);
102 root=0;
103 len=0;
104 insert(-inf);
105 insert(inf);
106 int ans=0;
107 int a=0,b=0;
108 for(int i=1;i<=n;++i)
109 {
110 int op,x;
111 scanf("%d%d",&op,&x);
112 if(op==0)
113 {
114 if(b)
115 {
116 int ans1=getpre(root,x);
117 int ans2=getsuf(root,x);
118 if(ans2-x<x-ans1) ans=(ans+abs(ans2-x))%mod,del(ans2);else ans=(ans+abs(ans1-x))%mod,del(ans1);
119 --b;
120 }
121 else ++a,insert(x);
122 }
123 else
124 {
125 if(a)
126 {
127 int ans1=getpre(root,x);
128 int ans2=getsuf(root,x);
129 if(ans2-x<x-ans1) ans=(ans+abs(ans2-x))%mod,del(ans2);else ans=(ans+abs(ans1-x))%mod,del(ans1);
130 --a;
131 }
132 else ++b,insert(x);
133 }
134 }
135 printf("%d\n",ans);
136 return 0;
137 }
自适应辛普森

1 #include<bits/stdc++.h>
2 using namespace std;
3 const double eps=1e-6;
4 double a,b,l,r;
5 double F(double x)
6 {
7 //Simpson公式用到的函数
8 return 2*sqrt(b*b-b*b*x*x/a/a);
9 }
10 double simpson(double l,double r)//三点Simpson法,这里要求F是一个全局函数
11 {
12 double mid=(l+r)*0.5;
13 return (F(l)+4*F(mid)+F(r))*(r-l)/6;
14 }
15 double asr(double l,double r)//自适应Simpson公式(递归过程)
16 {
17 double mid=(l+r)*0.5;
18 double x=simpson(l,mid),y=simpson(mid,r);
19 double z=simpson(l,r);
20 if(fabs(x+y-z)<=15*eps) return x+y+(x+y-z)/15.0;
21 return asr(l,mid)+asr(mid,r);
22 }
23 int main()
24 {
25 int T;
26 scanf("%d",&T);
27 while(T--)
28 {
29 scanf("%lf%lf%lf%lf",&a,&b,&l,&r);
30 printf("%.3f\n",asr(l,r));
31 }
32 return 0;
33 }
点分治

1 void getroot(int k,int fa)
2 {
3 sz[k]=mx[k]=1;
4 for(auto u:g[k])
5 {
6 if(u==fa||vis[u]) continue;
7 getroot(u,k);
8 sz[k]+=sz[u];
9 mx[k]=max(mx[k],sz[u]);
10 }
11 mx[k]=max(mx[k],sum-sz[k]);
12 if(mx[k]<mx[root]) root=k;
13 }
14 void getdeep(int k,int fa,int f)
15 {
16 father[k]=fa;
17 dep[k]=dep[fa]+1;
18 maxd[k]=dep[k];
19 par[k]=f;
20 L[k]=++t;
21 p[t]=k;
22 for(auto u:g[k])
23 {
24 if(u==fa||vis[u]) continue;
25 getdeep(u,k,f);
26 maxd[k]=max(maxd[k],maxd[u]);
27 }
28 R[k]=t;
29 }
30 void solve(int k)
31 {
32 t=0;
33 maxd[k]=dep[k]=0;
34 L[k]=++t;
35 p[1]=k;
36 for(auto u:g[k])
37 {
38 if(vis[u]) continue;
39 getdeep(u,k,u);
40 maxd[k]=max(maxd[k],maxd[u]);
41 }
42 R[k]=t;
43
44 for(int i=0;i<=maxd[k];++i) s[i]=0;
45 for(int i=1;i<=t;++i)
46 {
47 int u=p[i];
48 if(u>n) continue;
49 ++s[dep[u]];
50 if(dep[u]==D) res[k][par[u]]++;
51 }
52 ss[0]=s[0];
53 for(int i=1;i<=maxd[k];++i) ss[i]=ss[i-1]+s[i];
54 ans[k]+=ss[min(D-1,maxd[k])];
55 for(int i=2;i<=t;++i)
56 {
57 int u=p[i];
58 if(D-1-dep[u]>=0) ans[u]+=ss[min(D-1-dep[u],maxd[k])];
59 if(D>=dep[u]&&D-dep[u]<=maxd[k])
60 res[u][father[u]]+=s[D-dep[u]];
61 }
62
63 for(auto u:g[k])
64 {
65 if(vis[u]) continue;
66 for(int i=0;i<=maxd[u];++i) s[i]=ss[i]=0;
67 for(int i=L[u];i<=R[u];++i)
68 {
69 int v=p[i];
70 if(v>n) continue;
71 ++s[dep[v]];
72 }
73 ss[0]=s[0];
74 for(int i=1;i<=maxd[u];++i) ss[i]=ss[i-1]+s[i];
75 for(int i=L[u];i<=R[u];++i)
76 {
77 int v=p[i];
78 if(D-1-dep[v]>=0) ans[v]-=ss[min(D-1-dep[v],maxd[u])];
79 if(D>=dep[v]&&D-dep[v]<=maxd[u])
80 res[v][father[v]]-=s[D-dep[v]];
81 }
82 }
83 vis[k]=1;
84 for(auto u:g[k])
85 {
86 if(vis[u]) continue;
87 sum=sz[u];
88 root=0;
89 getroot(u,0);
90 solve(root);
91 }
92 }
带修改莫队

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1e6;
4 int block,n,m,num,s,l,r;
5 struct Q
6 {
7 int l,r,t,id;
8 bool operator < (const Q& x) const
9 {
10 if(l/block!=x.l/block) return l<x.l;
11 if(r/block!=x.r/block) return r<x.r;
12 return t<x.t;
13 }
14 }q[maxn+5];
15 struct wjmzbmr
16 {
17 int pos,from,to,t;
18 }c[maxn+5];
19 int a[maxn+5],b[maxn+5],color[maxn+5],ans[maxn+5];
20 void add(int x,int type)
21 {
22 if(color[x]) --s;
23 color[x]+=type;
24 if(color[x]) ++s;
25 }
26 void ins(wjmzbmr q)
27 {
28 if(q.pos>=l&&q.pos<=r) add(q.from,-1),add(q.to,1);
29 a[q.pos]=q.to;
30 }
31 void del(wjmzbmr q)
32 {
33 if(q.pos>=l&&q.pos<=r) add(q.to,-1),add(q.from,1);
34 a[q.pos]=q.from;
35 }
36 int main()
37 {
38 int T;
39 scanf("%d%d",&n,&T);
40 for(int i=1;i<=n;++i) scanf("%d",&b[i]),a[i]=b[i];
41 int time=0;
42 while(T--)
43 {
44 char s[3];
45 int x,y;
46 scanf("%s%d%d",s,&x,&y);
47 if(s[0]=='Q') ++m,q[m]={x,y,++time,m};
48 else c[++num]={x,0,y,++time};
49 }
50 for(int i=1;i<=num;++i) c[i].from=b[c[i].pos],b[c[i].pos]=c[i].to;
51 c[num+1].t=10000000;
52 block=(int)(ceil(pow(n,2.0/3)));
53 sort(q+1,q+m+1);
54 l=1,r=0;
55 int now=0;
56 s=0;
57 for(int i=1;i<=m;++i)
58 {
59 while(r<q[i].r) add(a[++r],1);
60 while(l>q[i].l) add(a[--l],1);
61 while(r>q[i].r) add(a[r--],-1);
62 while(l<q[i].l) add(a[l++],-1);
63 while(c[now+1].t<q[i].t) ins(c[++now]);
64 while(c[now].t>q[i].t) del(c[now--]);
65 ans[q[i].id]=s;
66 }
67 for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
68 return 0;
69 }
可持久化堆优化k短路

1 /*
2 可持久化堆优化k短路
3 求最短路径树:O(nlogn)
4 求k短路:O(mlogm+klogk)
5 空间复杂度:O(mlogm),但具体开数组要注意常数,要看执行merge操作的次数
6 */
7 #include<bits/stdc++.h>
8 using namespace std;
9 const int maxn=100000,maxm=200000,maxsize=3000000;//maxsize是堆的最大个数
10 const long long inf=1000000000000000LL;
11 int a[maxn+5];
12 long long s[maxn+5];
13 int n,k,m,len,tot;
14 int S,T;
15 vector<int> g1[maxn+5];
16 int mi[maxn+5],mx[maxn+5];
17 int head[maxn+5],nx[maxm+5];
18 long long dis[maxn+5];
19 int pos[maxn+5],rt[maxn+5];
20 struct Edge
21 {
22 int to;
23 long long w;
24 }e[maxm+5];
25 struct node
26 {
27 /*
28 u是当前堆顶的节点编号
29 key是当前堆顶对应边的权值,边的权值定义为:走这条边要多绕多少路
30 l,r分别是堆左右儿子的地址
31 */
32 int u;
33 long long key;
34 int l,r;
35 }H[maxsize+5];
36 struct heapnode
37 {
38 /*
39 求k短路时候用到的数据结构
40 len表示1~倒数第二条边的边权和
41 root表示倒数第二条边的tail的H[tail],其中堆顶就是最后一条边
42 */
43 long long len;
44 int root;
45 bool operator < (const heapnode& x) const
46 {
47 return len+H[root].key>x.len+H[x.root].key;
48 }
49 };
50 priority_queue<heapnode> q;
51 void addedge(int u,int v,long long w)
52 {
53
54 //printf("%d %d %lld\n",u,v,w);
55 e[++len]={v,w};
56 nx[len]=head[u];
57 head[u]=len;
58 }
59 void dfs(int k,int fa)
60 {
61 s[k]=a[k];
62 bool flag=0;
63 mi[k]=n+1;
64 mx[k]=0;
65 for(int i=0;i<g1[k].size();++i)
66 if(g1[k][i]!=fa)
67 {
68 flag=1;
69 dfs(g1[k][i],k);
70 s[k]+=s[g1[k][i]];
71 mi[k]=min(mi[k],mi[g1[k][i]]);
72 mx[k]=max(mx[k],mx[g1[k][i]]);
73 }
74 if(!flag) mi[k]=mx[k]=++m;
75 }
76 int newnode(int u,long long key)
77 {
78 ++tot;
79 H[tot]={u,key,0,0};
80 return tot;
81 }
82 int merge(int u,int v)
83 {
84 /*
85 merge两个堆u和v
86 这里是采用随机堆,方便合并,方便持久化
87 */
88 if(!u) return v;
89 if(!v) return u;
90 if(H[v].key<H[u].key) swap(u,v);
91 int k=++tot;
92 H[k]=H[u];
93 if(rand()%2) H[k].l=merge(H[k].l,v);
94 else H[k].r=merge(H[k].r,v);
95 return k;
96 }
97 void Kshort()
98 {
99 /*
100 求k短路
101 */
102 dis[T]=0;
103 for(int i=0;i<T;++i) dis[i]=inf;
104 tot=0;
105 for(int i=m-1;i>=0;--i)
106 {
107 /*
108 DAG图求最短路径树
109 */
110 int fa=0;
111 for(int j=head[i];j!=-1;j=nx[j])
112 if(dis[i]>e[j].w+dis[e[j].to])
113 {
114 dis[i]=e[j].w+dis[e[j].to];
115 pos[i]=j;
116 fa=e[j].to;
117 }
118 rt[i]=rt[fa];
119 for(int j=head[i];j!=-1;j=nx[j])
120 if(j!=pos[i])
121 {
122 //printf("ce : %d %d\n",i,e[j].to);
123 rt[i]=merge(rt[i],newnode(e[j].to,e[j].w+dis[e[j].to]-dis[i]));
124 }
125 }
126 //printf("tot : %d\n",tot);
127 //printf("len : %d\n",len);
128 //printf("m : %d\n",m);
129 //for(int i=0;i<=T;++i) printf("%d : %lld %d\n",i,dis[i],pos[i]);
130 printf("%lld\n",dis[S]+s[1]);
131 heapnode now={0LL,rt[S]};
132 if(now.root) q.push(now);
133 while(--k&&!q.empty())
134 {
135 /*
136 每次从优先队列队首取出最小的边集
137 每个边集对对应一种合法的k短路走法
138 有两种扩展方法
139 第一种:将最后一条边换成所在堆的次小元素(相当于从堆里把堆顶删除)
140 第二种:新加一条边,即从最后一条边继续往后走
141 */
142 now=q.top();
143 q.pop();
144 printf("%lld\n",now.len+H[now.root].key+dis[S]+s[1]);
145 int id=merge(H[now.root].l,H[now.root].r);
146 //printf("%d : %d %lld\n",id,H[id].u,H[id].key);
147 if(id)
148 q.push({now.len,id});
149 now.len+=H[now.root].key;
150 if(rt[H[now.root].u])
151 q.push({now.len,rt[H[now.root].u]});
152 }
153 }
154 int main()
155 {
156 srand(time(0));
157 scanf("%d%d",&n,&k);
158 for(int i=1;i<=n;++i) scanf("%d",&a[i]);
159 for(int i=1;i<n;++i)
160 {
161 int u,v;
162 scanf("%d%d",&u,&v);
163 g1[u].push_back(v);
164 g1[v].push_back(u);
165 }
166 dfs(1,0);
167 for(int i=0;i<=n+1;++i) head[i]=-1;
168 for(int i=2;i<=n;++i) addedge(mi[i]-1,mx[i],-s[i]);
169 for(int i=0;i<m;++i) addedge(i,i+1,0);
170 S=0,T=m;
171 Kshort();
172 return 0;
173 }
pbds里的rbtree

1 #include <bits/stdc++.h>
2 #include<ext/pb_ds/assoc_container.hpp>
3 //#include <bits/extc++.h>
4 using namespace std;
5 using namespace __gnu_pbds;
6 typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> rbtree;
7 /*
8 tree中不能有重复元素
9 若要能支持重复元素,可以将int改成pair<int,int>
10 */
11 int main()
12 {
13 rbtree s;
14 s.insert(8);
15 s.insert(3);
16 s.insert(5);
17 printf("%d\n",s.order_of_key(5));//s.order_of_key(x) s里面有多少数<x
18 printf("%d\n",*s.find_by_order(1));//s.find_by_order(k) s里面第k+1小的数是谁
19 return 0;
20 }
lagrange插值

1 void mul(int *a,int d,int c)
2 {
3 /*
4 a*(x-c)
5 */
6 int b[maxn+5];
7 // memset(b,0,sizeof(b));
8 for(int i=0;i<=d;++i) b[i]=a[i];
9 for(int i=d+1;i>=1;--i) a[i]=a[i-1];
10 a[0]=0;
11 for(int i=0;i<=d;++i)
12 {
13 a[i]=(a[i]-1LL*b[i]*c)%mod;
14 if(a[i]<0) a[i]+=mod;
15 }
16 }
17 void div(int *a,int d,int c,int *ans)
18 {
19 /*
20 ans=a/(x-c)
21 */
22 ans[d-1]=a[d];
23 for(int i=d-2;i>=0;--i)
24 ans[i]=(a[i+1]+1LL*c*ans[i+1])%mod;
25 }
26 void lagrange(int *y,int d,int *p)
27 {
28 /*
29 (0,y[0]),(1,y[1]),...,(d,y[d])
30 插出的系数放p中
31 */
32 int tmp[maxn+5],now[maxn+5];
33 memset(tmp,0,sizeof(tmp));
34 memset(now,0,sizeof(now));
35 tmp[0]=1;
36 for(int i=0;i<=d;++i)
37 {
38 mul(tmp,i,i);
39 }
40 for(int i=0;i<=d;++i)
41 {
42 for(int j=0;j<=d;++j) now[j]=0;
43 div(tmp,d+1,i,now);
44 long long q=1;
45 for(int j=0;j<=d;++j)
46 if(i!=j)
47 {
48 q=q*(i-j)%mod;
49 if(q<0) q+=mod;
50 }
51 q=inv(q);
52 q=q*y[i]%mod;
53 for(int j=0;j<=d;++j) now[j]=1LL*now[j]*q%mod;
54 for(int j=0;j<=d;++j) p[j]=(p[j]+now[j])%mod;
55 }
56 }
lagrange插值(插系数)

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=100,mod=1e9+7;
4 char s[10000+5];
5 int a[maxn+5][maxn+5],b[maxn+5][maxn+5],res[maxn+5][maxn+5];
6 int y[maxn+5];
7 int ans[maxn+5],p[maxn+5],num[maxn+5];
8 int n,k,d;
9 int det(int a[maxn+5][maxn+5],int n)
10 {
11 long long ans=1;
12 for(int i=1;i<=n;++i)
13 for(int j=i+1;j<=n;++j)
14 while(a[j][i])
15 {
16 int u=a[i][i]/a[j][i];
17 for(int k=1;k<=n;++k)
18 {
19 a[i][k]=(a[i][k]-1LL*u*a[j][k])%mod;
20 if(a[i][k]<0) a[i][k]+=mod;
21 swap(a[i][k],a[j][k]);
22 }
23 ans=-ans;
24 }
25 for(int i=1;i<=n;++i) ans=ans*a[i][i]%mod;
26 return ans;
27 }
28 void mul(int *a,int d,int c)
29 {
30 /*
31 a*(x-c)
32 */
33 int b[maxn+5];
34 for(int i=0;i<=d;++i) b[i]=a[i];
35 for(int i=d+1;i>=1;--i) a[i]=a[i-1];
36 a[0]=0;
37 for(int i=0;i<=d;++i)
38 {
39 a[i]=(a[i]-1LL*b[i]*c)%mod;
40 if(a[i]<0) a[i]+=mod;
41 }
42 }
43 void div(int *a,int d,int c,int *ans)
44 {
45 /*
46 ans=a/(x-c)
47 */
48 ans[d-1]=a[d];
49 for(int i=d-2;i>=0;--i)
50 ans[i]=(a[i+1]+1LL*c*ans[i+1])%mod;
51 }
52 long long Pow(long long a,long long b)
53 {
54 long long ans=1;
55 while(b)
56 {
57 if(b&1) ans=ans*a%mod;
58 a=a*a%mod;
59 b>>=1;
60 }
61 return ans;
62 }
63 long long inv(long long a)
64 {
65 return Pow(a,mod-2LL);
66 }
67 void lagrange(int *y,int d,int *p)
68 {
69 int tmp[maxn+5],now[maxn+5];
70 memset(tmp,0,sizeof(tmp));
71 memset(now,0,sizeof(now));
72 tmp[0]=1;
73 for(int i=0;i<=d;++i)
74 {
75 mul(tmp,i,i);
76 }
77 for(int i=0;i<=d;++i)
78 {
79 for(int j=0;j<=d;++j) now[j]=0;
80 div(tmp,d+1,i,now);
81 long long q=1;
82 for(int j=0;j<=d;++j)
83 if(i!=j)
84 {
85 q=q*(i-j)%mod;
86 if(q<0) q+=mod;
87 }
88 q=inv(q);
89 q=q*y[i]%mod;
90 for(int j=0;j<=d;++j) now[j]=1LL*now[j]*q%mod;
91 for(int j=0;j<=d;++j) p[j]=(p[j]+now[j])%mod;
92 }
93 }
94 void mul(int *a,int *b)
95 {
96 int tmp[maxn+5];
97 memset(tmp,0,sizeof(tmp));
98 for(int i=0;i<k;++i)
99 for(int j=0;j<k;++j)
100 tmp[i+j]=(tmp[i+j]+1LL*a[i]*b[j])%mod;
101 for(int i=k*2-2;i>=k;--i)
102 {
103 for(int j=k-1;j>=0;--j)
104 {
105 tmp[i-k+j]=(tmp[i-k+j]-1LL*tmp[i]*p[j])%mod;
106 if(tmp[i-k+j]<0) tmp[i-k+j]+=mod;
107 }
108 tmp[i]=0;
109 }
110 for(int i=0;i<k;++i) a[i]=tmp[i];
111 }
112 void mul(int a[maxn+5][maxn+5],int b[maxn+5][maxn+5],int n)
113 {
114 int ans[maxn+5][maxn+5];
115 memset(ans,0,sizeof(ans));
116 for(int i=1;i<=n;++i)
117 for(int j=1;j<=n;++j)
118 for(int k=1;k<=n;++k)
119 ans[i][j]=(ans[i][j]+1LL*a[i][k]*b[k][j])%mod;
120 for(int i=1;i<=n;++i)
121 for(int j=1;j<=n;++j)
122 a[i][j]=ans[i][j];
123 }
124 int main()
125 {
126 scanf("%s%d",s,&k);
127 n=strlen(s);
128 for(int i=1;i<=k;++i)
129 for(int j=1;j<=k;++j)
130 scanf("%d",&b[i][j]),b[i][j]=-b[i][j];
131 for(int x=0;x<=k;++x)
132 {
133 for(int i=1;i<=k;++i)
134 for(int j=1;j<=k;++j)
135 a[i][j]=b[i][j];
136 for(int i=1;i<=k;++i) a[i][i]=(b[i][i]+x)%mod;
137 y[x]=det(a,k);
138 }
139 lagrange(y,k,p);
140 ans[0]=1,num[1]=1;
141 for(int i=n-1;i>=0;--i)
142 {
143 if(s[i]=='1') mul(ans,num);
144 mul(num,num);
145 }
146 for(int i=1;i<=k;++i)
147 for(int j=1;j<=k;++j)
148 b[i][j]=-b[i][j];
149 memset(a,0,sizeof(a));
150 for(int i=1;i<=k;++i) a[i][i]=1;
151 for(int d=0;d<=k;++d)
152 {
153 for(int i=1;i<=k;++i)
154 for(int j=1;j<=k;++j)
155 res[i][j]=(res[i][j]+1LL*ans[d]*a[i][j])%mod;
156 mul(a,b,k);
157 }
158 for(int i=1;i<=k;++i)
159 {
160 for(int j=1;j<=k;++j)
161 {
162 if(res[i][j]<0) res[i][j]+=mod;
163 printf("%d",res[i][j]);
164 if(j!=k) printf(" ");
165 }
166 printf("\n");
167 }
168 return 0;
169 }
计算几何模板

1 typedef double db;
2 const db eps=1e-12;
3 struct Point
4 {
5 /*点类*/
6 db x,y;
7 Point(){}
8 Point(db _x,db _y):x(_x),y(_y){}
9 Point operator + (const Point &t)const
10 {
11 return Point(x+t.x,y+t.y);
12 }
13 Point operator - (const Point &t)const
14 {
15 return Point(x-t.x,y-t.y);
16 }
17 Point operator * (const db &t)const
18 {
19 return Point(x*t,y*t);
20 }
21 Point operator / (const db &t)const
22 {
23 return Point(x/t,y/t);
24 }
25 db operator * (const Point &t)const
26 {
27 return x*t.y-y*t.x;
28 }
29 db len()const
30 {
31 return sqrtl(x*x+y*y);
32 }
33 Point rot90()const
34 {
35 return Point(-y,x);
36 }
37 };
38 struct Complex
39 {
40 /*复数类,用于旋转*/
41 db x,y;
42 Complex(db x=0.0,db y=0.0):x(x),y(y){}
43 Complex operator + (const Complex &t)const
44 {
45 return Complex(x+t.x,y+t.y);
46 }
47 Complex operator - (const Complex &t)const
48 {
49 return Complex(x-t.x,y-t.y);
50 }
51 Complex operator * (const Complex &t)const
52 {
53 return Complex(x*t.x-y*t.y,x*t.y+y*t.x);
54 }
55 Complex operator / (const Complex &t)const
56 {
57 return Complex((x*t.x+y*t.y)/(t.x*t.x+t.y*t.y),(y*t.x-x*t.y)/(t.x*t.x+t.y*t.y));
58 }
59 };
60 struct Circle
61 {
62 /*圆类*/
63 Point o;
64 db r;
65 Circle(){}
66 Circle(Point _o,db _r):o(_o),r(_r){}
67 friend vector<Point> operator & (const Circle &c1,const Circle &c2)
68 {
69 /*
70 若两圆相离,返回空
71 若两圆相切,返回两个相同的点
72 若两圆相交,返回两个不同的点
73 */
74 db d=(c1.o-c2.o).len();
75 if(d>c1.r+c2.r+eps||d<fabs(c1.r-c2.r)-eps) return vector<Point>();
76 db dt=(c1.r*c1.r-c2.r*c2.r)/d,d1=(d+dt)/2;
77 Point dir=(c2.o-c1.o)/d,pcrs=c1.o+dir*d1;
78 dt=sqrt(max(0.0L,c1.r*c1.r-d1*d1)),dir=dir.rot90();
79 return vector<Point>{pcrs+dir*dt,pcrs-dir*dt};
80 }
81 };
82 void calcentre()
83 {
84 /*
85 计算凸多边形的重心
86 将凸多边形划分成若干小三角形,求出三角形的重心,然后根据小三角形面积求加权平均
87 */
88 db area=0.0;
89 for(int i=2;i<n;++i) area+=(a[i+1]-a[i])*(a[1]-a[i]);
90 g=Point(0,0);
91 for(int i=2;i<n;++i)
92 {
93 db s=(a[i+1]-a[i])*(a[1]-a[i]);
94 g=g+(a[1]+a[i]+a[i+1])/3.0*(s/area);
95 }
96 }
k^2logn求线性递推

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=4000,mod=1000000007;
4 int a[maxn+5],p[maxn+5],ans[maxn+5],num[maxn+5];
5 int h[maxn+5],tmp[maxn+5];
6 int n,k;
7 void mul(int *a,int *b,int *ans)
8 {
9 for(int i=0;i<=2*k;++i) tmp[i]=0;
10 for(int i=0;i<k;++i)
11 for(int j=0;j<k;++j)
12 tmp[i+j]=(tmp[i+j]+1LL*a[i]*b[j])%mod;
13 for(int i=2*k-2;i>=k;--i)
14 {
15 for(int j=k-1;j>=0;--j)
16 tmp[i-k+j]=(tmp[i-k+j]-1LL*tmp[i]*p[j])%mod,tmp[i-k+j]=(tmp[i-k+j]+mod)%mod;
17 tmp[i]=0;
18 }
19 for(int i=0;i<k;++i) ans[i]=tmp[i];
20 }
21 int main()
22 {
23 scanf("%d%d",&n,&k);
24 for(int i=1;i<=k;++i) scanf("%d",&a[i]);
25 for(int i=0;i<k;++i) scanf("%d",&h[i]);
26 p[k]=1;
27 for(int i=1;i<=k;++i) p[k-i]=mod-a[i];
28 for(int i=k;i<2*k;++i)
29 for(int j=1;j<=k;++j)
30 {
31 h[i]=h[i]+1LL*h[i-j]*a[j]%mod;
32 h[i]%=mod;
33 }
34 if(n<2*k) return 0*printf("%d\n",h[n]);
35 int b=n-k+1;
36 num[1]=1,ans[0]=1;
37 while(b)
38 {
39 if(b&1) mul(ans,num,ans);
40 mul(num,num,num);
41 b>>=1;
42 }
43 long long res=0;
44 for(int i=0;i<k;++i) res=(res+1LL*ans[i]*h[i+k-1])%mod;
45 printf("%lld\n",(res+mod)%mod);
46 return 0;
47 }
数位dp

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int mod=1e9+7;
4 int dp[65][3][128];
5 int a[65];
6 long long n;
7 int dfs(int len,int pre,int sum,bool flag)
8 {
9 if(!flag&&dp[len][pre][sum]!=-1) return dp[len][pre][sum];
10 if(!len) return abs(sum-64);
11 int ans=0;
12 int limit=flag?a[len]:1;
13 for(int i=0;i<=limit;++i)
14 {
15 if(pre==2)
16 {
17 if(i) ans=(ans+dfs(len-1,i,sum,flag&&i==a[len]))%mod;
18 else ans=(ans+dfs(len-1,pre,sum,flag&&i==a[len]))%mod;
19 }
20 else
21 {
22 if(pre==i) ans=(ans+dfs(len-1,i,sum+1,flag&&i==a[len]))%mod;
23 else ans=(ans+dfs(len-1,i,sum-1,flag&&i==a[len]))%mod;
24 }
25 }
26 if(!flag) dp[len][pre][sum]=ans;
27 return ans;
28 }
29 int main()
30 {
31 memset(dp,-1,sizeof(dp));
32 int T;
33 scanf("%d",&T);
34 while(T--)
35 {
36 scanf("%lld",&n);
37 int len=0;
38 while(n)
39 {
40 a[++len]=n%2;
41 n/=2;
42 }
43 printf("%d\n",dfs(len,2,0+64,1));
44 }
45 return 0;
46 }
BigInt

1 typedef long long LL;
2 struct BigInt
3 {
4 static const int BASE = 100000000; //基数
5 static const int WIDTH = 32; //基宽
6 vector<int> s; //存储
7
8 //构造函数 -- 使用LL
9 BigInt(long long num = 0)
10 {
11 *this = num;
12 }
13
14 //赋值运算符 -- 使用LL
15 BigInt operator = (long long num)
16 {
17 s.clear();
18 do
19 {
20 s.push_back(num % BASE);
21 num /= BASE;
22 }
23 while(num > 0);
24 return *this;
25 }
26 //赋值运算符 -- 使用string
27 BigInt operator = (const string& str)
28 {
29 s.clear();
30 int x, len = (str.length() - 1) / WIDTH + 1;
31 for(int i = 0; i < len; i++)
32 {
33 int end = str.length() - i*WIDTH;
34 int start = max(0, end - WIDTH);
35 sscanf(str.substr(start, end-start).c_str(), "%d", &x);
36 s.push_back(x);
37 }
38 return *this;
39 }
40
41 //比较运算符
42 bool operator < (const BigInt& b) const
43 {
44 if(s.size() != b.s.size()) return s.size() < b.s.size();
45 for(int i = s.size()-1; i >= 0; i--)
46 if(s[i] != b.s[i]) return s[i] < b.s[i];
47 return false; //相等
48 }
49 bool operator > (const BigInt& b) const
50 {
51 return b < *this;
52 }
53 bool operator <= (const BigInt& b) const
54 {
55 return !(b < *this);
56 }
57 bool operator >= (const BigInt& b) const
58 {
59 return !(*this < b);
60 }
61 bool operator != (const BigInt& b) const
62 {
63 return b < *this || *this < b;
64 }
65 bool operator == (const BigInt& b) const
66 {
67 return !(b < *this) && !(*this < b);
68 }
69
70 //重载输入输出
71 friend ostream& operator << (ostream &out, const BigInt& x)
72 {
73 out << x.s.back();
74 for(int i = x.s.size()-2; i >= 0; i--)
75 {
76 char buf[20];
77 sprintf(buf, "%08d", x.s[i]);
78 for(int j = 0; j < strlen(buf); j++) out << buf[j];
79 }
80 return out;
81 }
82 friend istream& operator >> (istream &in, BigInt& x)
83 {
84 string s;
85 if(!(in >> s)) return in;
86 x = s;
87 return in;
88 }
89
90 //加法
91 BigInt operator + (const BigInt& b) const
92 {
93 BigInt c;
94 c.s.clear();
95 for(int i = 0, g = 0; ; i++)
96 {
97 if(g == 0 && i >= s.size() && i >= b.s.size()) break;
98 int x = g;
99 if(i < s.size()) x += s[i];
100 if(i < b.s.size()) x += b.s[i];
101 c.s.push_back(x % BASE);
102 g = x / BASE;
103 }
104 return c;
105 }
106
107 //加等于
108 BigInt operator += (const BigInt& b)
109 {
110 *this = *this + b;
111 return *this;
112 }
113
114
115
116 //减法 -- 大减小 -- 其他的在外部处理
117 BigInt operator - (const BigInt& b) const
118 {
119 BigInt c;
120 c.s.clear();
121 if((*this) == b) return c = 0;
122 for(int i = 0, g = 0; ; ++i)
123 {
124 if(g == 0 && i >= s.size() && i >= b.s.size()) break;
125 int x = -g;
126 g = 0;
127 if(i < s.size()) x += s[i];
128 if(i < b.s.size()) x -= b.s[i];
129 if(x < 0) x += BASE, ++g;
130 c.s.push_back(x);
131 }
132 for(int i = c.s.size()-1; i >= 0 && c.s[i] == 0; --i) c.s.pop_back();
133 return c;
134 }
135
136
137 //乘法 -- 未使用FFT
138 BigInt operator * (const BigInt& b) const
139 {
140 int s1 = s.size(), s2 = b.s.size();
141 vector<LL> v(s1+s2+1,0);
142 BigInt c;
143 c.s.resize(s1+s2, 0);
144 for(int i = 0; i < s1; ++i) //相乘
145 for(int j = 0; j < s2; ++j)
146 {
147 v[i+j] += (LL)s[i]*b.s[j];
148 }
149 for(int i = 0; i < s1+s2; ++i) //进位
150 {
151 v[i+1] += v[i]/BASE;
152 v[i] %= BASE;
153 c.s[i] = v[i];
154 }
155 for(int i = c.s.size()-1; i >= 0 && c.s[i] == 0; --i) c.s.pop_back();
156 return c;
157 }
158
159 //除法 -- 二分
160 BigInt operator / (const BigInt& b) const
161 {
162 int s1 = s.size(), s2 = b.s.size();
163 int len = s1-s2;
164 BigInt c, x = *this, y = b;
165 if(len < 0) return c = 0;
166
167 c.s.resize(len+1, 0);
168 for(int i = len; i >= 0; --i)
169 {
170 //先将除数对齐
171 y.s.resize(s2+i,0);
172 for(int j = s2+i-1; j >= 0; --j)
173 {
174 if(j >= i) y.s[j] = b.s[j-i];
175 else y.s[j] = 0;
176 }
177 //再二分找商
178 int L = 0, R = BASE;
179 BigInt t;
180 while(L < R)
181 {
182 int mid = (L+R)>>1;
183 t = mid;
184 if(t*y > x) R = mid;
185 else L = mid+1;
186 }
187 c.s[i] = L-1;
188 //更新被除数
189 t = L-1;
190 x = x - t*y;
191 }
192 for(int i = c.s.size()-1; i >= 0 && c.s[i] == 0; --i) c.s.pop_back();
193 return c;
194 }
195
196 //取模
197 BigInt operator % (const BigInt& b) const
198 {
199 return (*this) - (*this)/b * b;
200 }
201
202 //开方 -- 二分 -- 浮点数可放大1e4精确一位
203 BigInt Sqrt()
204 {
205 BigInt L = 1, R = *this;
206 while(L < R)
207 {
208 BigInt mid = (L+R)/2;
209 if(mid*mid > *this) R = mid;
210 else L = mid+1;
211 }
212 return L-1;
213 }
214 };
CRT

1 void gcd(ll a,ll b,ll &d,ll &x,ll &y)
2 {
3 if(!b)
4 {
5 d=a,x=1,y=0;
6 return;
7 }
8 gcd(b,a%b,d,y,x);
9 y-=x*(a/b);
10 }
11 ll inv(ll a,ll n)
12 {
13 ll d,x,y;
14 gcd(a,n,d,x,y);
15 return d==1?(x+n)%n:-1;
16 }
17 ll CRT(int n,ll *a,ll *m)
18 {
19 /*n个方程 x=a[i] (mod m[i]) (0<=i<n)*/
20 ll M=1,d,y,x=0;
21 for(int i=0;i<n;++i) M*=m[i];
22 for(int i=0;i<n;++i)
23 {
24 ll w=M/m[i];
25 gcd(m[i],w,d,d,y);
26 x=(x+y*w*a[i])%M;
27 }
28 return (x+M)%M;
29 }
类欧几里得

1 typedef long long ll;
2 const ll mod = 998244353;
3
4 ll solve(ll a,ll b,ll c,ll n)
5 {
6 /*
7 计算 \sum_{i=0..n} (ax+b)/c 的值
8 即第一象限直线y=(ax+b)/c下方纵坐标为正数的整点的个数
9 */
10 if(a==0)
11 return (b/c)*(n+1)%mod;
12 if(a>=c)
13 return (n*(n+1)/2%mod*(a/c)%mod+solve(a%c,b,c,n))%mod;
14 if(b>=c)
15 return ((b/c)*(n+1)%mod+solve(a,b%c,c,n))%mod;
16 //LL m=(a*n+b)/c%MOD;
17 ll m=(n/c*a+(n%c*a+b)/c);
18 return ((m%mod)*(n%mod)%mod-solve(c,c-b-1,a,m-1)+mod)%mod;
19 }
20 ll cal(ll a,ll b,ll c,ll n)
21 {
22 /*
23 计算y=(ax+b)/c下方整点个数,x=0..n
24 要求a>=0,c>0
25 */
26 if(b>=0) return (solve(a,b,c,n)+n%mod+1)%mod;
27 ll x=(-b)/a;
28 if(x*a+b<0) ++x;
29 if(n<x) return 0;
30 b+=a*x;
31 return (solve(a,b,c,n-x)+(n-x)%mod+1)%mod;
32 }
笛卡尔树

1 pair<int,int> a[maxn+5];
2 int lson[maxn+5],rson[maxn+5],fa[maxn+5],root;
3 int s[maxn+5];
4 void buildtreap(pair<int,int> *a)
5 {
6 /*
7 大根堆
8 */
9 int top=0;
10 for(int i=0;i<=n;++i) rson[i]=lson[i]=fa[i]=0;
11 for(int i=1;i<=n;++i)
12 {
13 int last=0;
14 while(top>=1&&a[i]>a[s[top]]) last=s[top--];
15 if(top) rson[s[top]]=i,fa[i]=s[top];
16 lson[i]=last;
17 if(!last) fa[last]=i;
18 s[++top]=i;
19 }
20 root=s[1];
21 }
杜教筛求莫比乌斯函数前缀和

1 #include <bits/stdc++.h>
2 using namespace std;
3 #define clr(a, x) memset(a, x, sizeof(a))
4 typedef long long ll;
5 const int maxn = 1e6 + 5;
6 int prime[maxn], tot, mu[maxn], Mu[maxn];
7 bool check[maxn];
8 map<ll, ll> M;
9 map<ll, ll> T;
10 void calmu()
11 {
12 mu[1] = 1;
13 for (int i = 2; i < maxn; i++)
14 {
15 if (!check[i])
16 prime[tot++] = i, mu[i] = -1;
17 for (int j = 0; j < tot; j++)
18 {
19 if (i * prime[j] >= maxn) break;
20 check[i * prime[j]] = true;
21 if (i % prime[j] == 0)
22 {
23 mu[i * prime[j]] = 0;
24 break;
25 }
26 else
27 mu[i * prime[j]] = -mu[i];
28 }
29 }
30 for (int i = 1; i < maxn; i++)
31 Mu[i] = Mu[i - 1] + mu[i];
32 }
33 ll work(ll x)
34 {
35 /*
36 求 mu[1]+mu[2]+...+mu[x]
37 */
38 if (x < maxn) return Mu[x];
39 if (M[x]) return M[x];
40 ll ans = 1;
41 for (ll i = 2, last; i <= x; i = last + 1)
42 {
43 last = x / (x / i);
44 ans -= (last - i + 1) * work(x / i);
45 }
46 return M[x] = ans;
47 }
O(1)快速乘

1 inline ll multi(ll x,ll y,ll mod)
2 {
3 ll tmp=(x*y-(ll)((long double)x/mod*y+1.0e-8)*mod);
4 return tmp<0 ? tmp+mod : tmp;
5 }
莫队算法

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=40000;
4 int pos[maxn+5],a[maxn+5];
5 struct wjmzbmr
6 {
7 int l,r,k1,k2,id,ans;
8 }q[maxn+5];
9 int block,n,m;
10 int color[maxn+5],cnt[200+5],ans[maxn+5];
11 int num[maxn+5],sum[maxn+5][200+5];
12 bool cmp(const wjmzbmr a,const wjmzbmr b)
13 {
14 if(a.l/block!=b.l/block) return a.l<b.l;
15 if((a.l/block)&1) return a.r>b.r;else return a.r<b.r;
16 }
17 void update(int x,int type)
18 {
19 --color[num[x]];
20 if(color[num[x]]==0) --cnt[num[x]/block];
21 --sum[num[x]][x/block];
22 num[x]+=type;
23 ++sum[num[x]][x/block];
24 if(color[num[x]]==0) ++cnt[num[x]/block];
25 ++color[num[x]];
26 }
27 int query(int k1,int k2)
28 {
29 int i=0;
30 for(i=0;i<=n/block;++i)
31 if(cnt[i]<k1) k1-=cnt[i];
32 else break;
33 int turn;
34 for(turn=block*i;turn<block*(i+1);++turn)
35 {
36 if(color[turn]>0) --k1;
37 if(k1==0) break;
38 }
39 for(i=0;i<=200;++i)
40 if(sum[turn][i]<k2) k2-=sum[turn][i];
41 else break;
42 int ans;
43 for(ans=block*i;ans<block*(i+1);++ans)
44 {
45 if(num[ans]!=turn) continue;
46 if(num[ans]>0) --k2;
47 if(k2==0) break;
48 }
49 return ans;
50 }
51 int main()
52 {
53 scanf("%d",&n);
54 for(int i=1;i<=n;++i) scanf("%d",&a[i]);
55 scanf("%d",&m);
56 for(int i=1;i<=m;++i) scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].k1,&q[i].k2),q[i].id=i;
57 block=sqrt(n);
58 sort(q+1,q+m+1,cmp);
59 block=200;
60 int l=1,r=0;
61 for(int i=1;i<=m;++i)
62 {
63 while(l>q[i].l) update(a[--l],1);
64 while(r<q[i].r) update(a[++r],1);
65 while(r>q[i].r) update(a[r--],-1);
66 while(l<q[i].l) update(a[l++],-1);
67 ans[q[i].id]=query(q[i].k1,q[i].k2);
68 }
69 for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
70 return 0;
71 }
来源:https://www.cnblogs.com/wmrv587/p/5915095.html
