# codebook `pq_vser.cpp` ```c++= struct vser{ bool operator()(INT a,INT b){ return a.id>b.id; } }; priority_queue<INT,vector<INT>,vser> pq; ``` `basic.cpp` ```c++= /* [q] [] */ //#ifndef eval #include<bits/stdc++.h> using namespace std; #define INT long long int #define endl "\n" #define read(n) reader<n>() #define DBG if(debug) #define PII pair<INT,INT> bool debug=0; bool noTLE=1; template<typename tpe>tpe reader(){ tpe re;cin>>re;return re; } int main(int argc,char** argv){ for(int i=0;i<argc;i++){ string nwstr=argv[i]; if(nwstr=="-Dev"){ debug=1; noTLE=0; }else if(nwstr=="-TLE"){ noTLE=0; } } if(noTLE && !debug)cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); DBG{ cout<<"Temp by KagariET01"<<endl; cout<<"My Webpage: https://kagariet01.github.io/about"<<endl; cout<<"===DBG mod on==="<<endl; cout<<"Here's your CFG"<<endl; for(int i=0;i<argc;i++){ string nwstr=argv[i]; cout<<'['<<nwstr<<']'<<endl; } cout<<"===Code start==="<<endl; } INT t=read(int); while(t--){ } return 0; } //#endif ``` > DP > > `LCS_1.cpp` > > ```c++= > > /* > > [LCS] > > [最長共用子序列] > > string s,t; > > INT dp[3001][3001]; > > bool debug=false; > > /*fn定義*/ > > void lcs(INT n,INT m){ > > for(INT i=1;i<=n;i++){ > > for(INT j=1;j<=m;j++){ > > if(s[i-1]==t[j-1]){ > > dp[i][j]=dp[i-1][j-1]+1; > > }else dp[i][j]=max(dp[i-1][j],dp[i][j-1]); > > } > > } > > } > > void printdp(INT n,INT m){ > > if(debug){ > > for(INT i=0;i<=n;i++){ > > for(INT j=0;j<=m;j++){ > > cout<<dp[i][j]<<","; > > } > > cout<<endl; > > } > > cout<<endl; > > } > > } > > string backlcs(INT n,INT m){ > > string re=""; > > INT i=n,j=m; > > while(i && j){ > > if(s[i-1]==t[j-1]){ > > re.push_back(s[i-1]); > > i--; > > j--; > > }else{ > > if(dp[i-1][j]>=dp[i][j-1]){ > > i--; > > }else j--; > > } > > } > > reverse(re.begin(),re.end()); > > return re; > > } > > /*main*/ > > int main(){ > > /*IO加速*/ > > if(!debug)> > > {cin.tie(0);cout.tie(0);ios::sync_with_stdio(false);} > > /*CIN*/ > > cin>>s>>t; > > /*solve*/ > > INT ss=s.length(),ts=t.length(); > > lcs(ss,ts); > > printdp(ss,ts); > > cout<<backlcs(ss,ts); > > return 0; > > } > > ``` > > `LIS_1.cpp` > > ```c++= > > /* > > [LIS] > > [最長遞增子序列] > > int main(){ > > ios_base::sync_with_stdio(0); > > cin.tie(0); > > //cin > > int num; > > vector<int> a; > > while (cin >> num){ > > a.push_back(num); > > } > > //solve > > int N = (int) a.size();//計算DP大小 > > int dp[N+1];//建立dp > > vector<int> v;//已走訪過的數字 > > dp[0] = 1;//dp初始化 > > v.push_back(a[0]);//v初始化 > > > > int L = 1; //LIS length > > //L為長度 > > for (int i=1; i<N; i++){ > > if (a[i] > v.back()){//如果現在這個大於v最頂端的 > > v.push_back(a[i]);//先將自己推進v > > L++;//長度增加 > > dp[i] = L; > > } else { > > auto it = lower_bound(v.begin(), v.end(), a[i]);//尋找v裡面最第一個大於等於她的數 > > *it = a[i];//將此數換成更小的數(自己) > > dp[i] = (int) (it - v.begin() + 1);//計算長度,因為此vector是遞增子序列,直接量他的size就可以了 > > } > > } > > cout << L << "\n-\n"; > > //尋找順序 > > vector<int> ans; > > for (int i=N-1; i>=0; i--){//由後往前 > > if (dp[i] == L){ > > ans.push_back(a[i]);//找到的話就把元素塞進ans > > L--; > > } > > } > > reverse(ans.begin(), ans.end());//ans反向 > > //輸出順序 > > for (auto i: ans){ > > cout << i << '\n'; > > } > > return 0; > > } > math > > mod > > > `Extended_Euclidean.cpp` > > > ```c++= > > > /* > > > [擴展歐幾里得]https://zh.wikipedia.org/wiki/扩展欧几里得算法#算法和举例 > > > */ > > > > > > #include<iostream> > > > template<typename TPE>std::pair<TPE,std::pair<TPE,TPE>> Extended_Euclidean(TPE a,TPE b){ > > > TPE lst[3][3]={ > > > {a,1,0}, > > > {b,0,1}, > > > {0,0,0} > > > }; > > > int i=2; > > > for(i=2;lst[(i+2)%3][0];i=(i+1)%3){ > > > TPE q=lst[(i+1)%3][0]/lst[(i+2)%3][0]; > > > lst[i][0]=lst[(i+1)%3][0]-lst[(i+2)%3][0]*q; > > > lst[i][1]=lst[(i+1)%3][1]-lst[(i+2)%3][1]*q; > > > lst[i][2]=lst[(i+1)%3][2]-lst[(i+2)%3][2]*q; > > > } > > > i=(i+1)%3; > > > std::pair<TPE,std::pair<TPE,TPE>> re={lst[i][0],{lst[i][1],lst[i][2]}}; > > > re=(re%b+b)%b > > > return re; > > > } > > > int main(){ > > > int a,b; > > > std::cin>>a>>b; > > > std::pair<int,std::pair<int,int>> ans=Extended_Euclidean(a,b); > > > std::cout<<ans.first<<" "<<ans.second.first<<" "<<ans.second.second<<std::endl; > > > } > > > ``` > > > `Modular_multiplicative_inverse.cpp` > > > ```c++= > > > /* > > > [求反模逆元 a^(-1) mod n] > > > */ > > > > > > #include<iostream> > > > > > > template<typename TPE>std::pair<TPE,std::pair<TPE,TPE>> Extended_Euclidean(TPE a,TPE b){//擴展歐幾里得 > > > TPE lst[3][3]={ > > > {a,1,0}, > > > {b,0,1}, > > > {0,0,0} > > > }; > > > int i=2; > > > for(i=2;lst[(i+2)%3][0];i=(i+1)%3){ > > > TPE q=lst[(i+1)%3][0]/lst[(i+2)%3][0]; > > > lst[i][0]=lst[(i+1)%3][0]-lst[(i+2)%3][0]*q; > > > lst[i][1]=lst[(i+1)%3][1]-lst[(i+2)%3][1]*q; > > > lst[i][2]=lst[(i+1)%3][2]-lst[(i+2)%3][2]*q; > > > } > > > i=(i+1)%3; > > > std::pair<TPE,std::pair<TPE,TPE>> re={lst[i][0],{lst[i][1],lst[i][2]}}; > > > return re; > > > } > > > > > > template<typename TPE>TPE Modular_multiplicative_inverse(TPE a,TPE n){//用擴展歐幾里得求模逆元 > > > std::pair<TPE,std::pair<TPE,TPE>> ans=Extended_Euclidean(a,n); > > > TPE re=ans.second.first; > > > re=(re%n+n)%n; > > > if(ans.first==1)return re; > > > else return -1; > > > } > > > > > > > > > int main(){ > > > int a,b; > > > std::cin>>a>>b; > > > int ans=Modular_multiplicative_inverse(a,b); > > > std::cout<<ans<<std::endl; > > > } > > > ``` > > > > > > > `Geometry.cpp` > > ```c++= > > /* > > [Q] > > [] > > */ > > #include<cmath> > > #include<bits/stdc++.h> > > using namespace std; > > #define INT long long int > > #define endl "\n" > > #define read(n) reader<n>() > > template<typename TPE>TPE reader(){ > > TPE re;cin>>re;return re; > > } > > bool debug=0; > > > > > > /* > > eps=浮點數誤差值 > > */ > > const double eps=1e-9;//浮點數誤差 > > > > /* > > 向量Vec > > 也可當點使用 > > */ > > struct Vec{//點、向量 > > double x=0,y=0; > > void setv(const double &a,const double &b){ > > x=a,y=b; > > } > > }; > > Vec make_Vec(const double &a,const double &b){ > > Vec re; > > re.x=a,re.y=b; > > return re; > > } > > > > struct Seg{//線段 > > Vec p1,p2; > > }; > > > > Seg make_Seg(Vec a,Vec b){//將兩點Vec合併成線段Seg > > Seg re; > > re.p1=a; > > re.p2=b; > > return re; > > } > > > > /* > > 基本運算 > > */ > > Vec operator-(const Vec &a,const Vec &b){ > > Vec re; > > re.x=b.x-a.x; > > re.y=b.y-a.y; > > return re; > > } > > Vec operator+(const Vec &a,const Vec &b){ > > Vec re; > > re.x=b.x+a.x; > > re.y=b.y+a.y; > > return re; > > } > > Vec operator*(const Vec &a,const double &n){ > > return make_Vec(a.x*n,a.y*n); > > } > > Vec operator*(const double &n,const Vec &a){ > > return a*n; > > } > > Vec operator/(const Vec &a,const double &n){ > > return make_Vec(a.x/n,a.y/n); > > } > > Vec operator/(const double &n,const Vec &a){ > > return a/n; > > } > > bool operator<(const Vec &a,const Vec &b){ > > return (a.x*a.x+a.y*a.y)<(b.x*b.x+b.y*b.y); > > } > > bool operator<=(const Vec &a,const Vec &b){ > > return (a.x*a.x+a.y*a.y)<=(b.x*b.x+b.y*b.y); > > } > > bool operator>(const Vec &a,const Vec &b){ > > return (a.x*a.x+a.y*a.y)>(b.x*b.x+b.y*b.y); > > } > > bool operator>=(const Vec &a,const Vec &b){ > > return (a.x*a.x+a.y*a.y)>=(b.x*b.x+b.y*b.y); > > } > > bool operator==(const Vec &a,const Vec &b){ > > return (a.x==b.x && a.y==b.y); > > } > > > > /* > > 內積* > > AB內積=A的長度*B的長度*cos(AB夾角) > > 內積=0:兩向量垂直 > > 內積>0 夾角<90度 > > 內積<0 夾角>90度 > > */ > > double Dot(const Vec &a,const Vec &b){ > > return a.x*b.x+a.y*b.y; > > } > > double operator*(const Vec &a,const Vec &b){ > > return Dot(a,b); > > } > > > > /* > > 外積^ > > AB外積=A的長度*B的長度*sin(AB夾角)=OAB三角形面積 > > B的長度*sin(AB夾角)=OAB的高(底為OA) > > > > 外積=0:兩向量平行 > > 外積>0 B 向量在 A 向量的逆時針方向 > > 外積<0 B 向量在 A 向量的順時針方向 > > */ > > double cross(const Vec &a,const Vec &b){ > > return a.x*b.y-a.y*b.x; > > } > > double operator^(const Vec &a,const Vec &b){ > > return cross(a,b); > > } > > > > /* > > 多邊形Polygon > > 裡面存的是點 > > */ > > struct Polygon{//建立多邊形Polygon > > vector<Vec> vec; > > void push_back(Vec a){ > > vec.push_back(a); > > } > > void push_back(double x,double y){ > > vec.push_back(make_Vec(x,y)); > > } > > long long int size(){ > > return vec.size(); > > } > > Vec back(){ > > return vec.back(); > > } > > bool empty(){ > > return vec.empty(); > > } > > void pop_back(){ > > vec.pop_back(); > > } > > void pop_front(){ > > vec.erase(vec.begin()); > > } > > Vec front(){ > > return vec.front(); > > } > > vector<Vec>::iterator begin(){ > > return vec.begin(); > > } > > vector<Vec>::iterator end(){ > > return vec.end(); > > } > > Vec operator[](unsigned long long int n){ > > return vec[n]; > > } > > }; > > > > /* > > 面積Area > > 將O(0,0)視為開始點 > > 連線向量O->P_1和O->P_2...... > > 對向量V1和V2計算三角形面積 > > 全部總和即為所求 > > */ > > double Area(Polygon Pol){//對Polygon計算面積 > > double re=0; > > long long int Polsz=Pol.size(); > > if(Polsz==0)return 0; > > for(INT i=0;i<Polsz;i++){ > > re+=Pol.vec[i]^Pol.vec[(i+1)%Polsz]; > > } > > return fabs(re/2); > > } > > > > /* > > 判斷方向ori > > 第一行:值取絕對值之後,誤差小於eps就算是0 > > o代表旋轉點,a代表點a,b代表點b > > 判斷oa轉道ob要轉哪個方向 > > */ > > int sign(double a){//對double簡化成-1,0,1 > > if(fabs(a)<eps)return 0; > > else return a>0?1:-1; > > } > > int ori(const Vec &o,const Vec &a,const Vec &b){//判斷方向,0為同向or 180,1為逆時針,-1為順時針 > > return sign((a-o)^(b-o)); > > } > > > > /* > > 點C是否在線AB上btw > > 以c為中心點,a和b不在同個方向,那答案一定是False > > 最後檢查角度,如果角度>90,那就一定是180,也就是C在AB上 > > 如果角度<90,那就一定是0,就代表C不在AB上 > > */ > > bool btw(const Vec &pa,const Vec &pb,const Vec &pc){//檢測C是否在AB上 > > if(ori(pc,pa,pb))return false; > > else return ((pa-pc)*(pb-pc))<=0; > > } > > bool btw(const Seg &la,const Vec &p){ > > return btw(la.p1,la.p2,p); > > } > > > > /* > > 檢測是否相交Banana > > 考慮下面幾種情況 > > > > C > > | > > A-+-B > > | > > D > > > > A---B > > C > > | > > D > > > > 我們可以發現,以A為中心,連到B,C,D > > 可以發現C一定要在B的逆時針方向(or順時針) > > 而D則在B的另一方向 > > 同理,其他點也一樣 > > 將方向改成數值表示 > > 一個一定會是-1 > > 另一個一定會是1 > > 相乘就是-1 > > 我們只要判斷相乘是不是<0即可 > > > > 另一種情況 > > > > A-C-B > > | > > D > > 如果有一個點(C)在線上(AB) > > 那另外一個點(D)在哪都行(可-1可1) > > 對於剛剛的判斷式,只要把<0改成<=0即可 > > 那還有另一種情況如下 > > > > A-C=B-D > > > > > > > > */ > > bool havebanana(const Vec &pa,const Vec &pb,const Vec &pc,const Vec &pd){//檢測兩線段是否相交 > > int a123=ori(pa,pb,pc); > > int a124=ori(pa,pb,pd); > > int a341=ori(pc,pd,pa); > > int a342=ori(pc,pd,pb); > > if(a123==0 && a124==0){ > > return btw(pa,pb,pc)||btw(pa,pb,pd)||btw(pc,pd,pa)||btw(pc,pd,pb); > > }else return a123*a124<=0 && a341*a342<=0; > > } > > bool havebanana(const Seg &la,const Seg &lb){ > > return havebanana(la.p1,la.p2,lb.p1,lb.p2); > > } > > > > /* > > 取得交點getbanana > > 考慮下面幾種情況 > > > > C > > /|\ > > A-E-B > > \|/ > > D > > 求AB和CD交點 > > AE:EB=CAD:CBD > > E=(A*CBD+B*CAD)/(CAD+CBD) > > */ > > pair<bool,Vec> getbanana(const Vec &pa,const Vec &pb,const Vec &pc,const Vec &pd){ > > pair<bool,Vec> re; > > re.first=havebanana(pa,pb,pc,pd); > > if(!re.first)return re; > > double CBD=fabs((pc-pb)^(pd-pb)); > > double CAD=fabs((pc-pa)^(pd-pa)); > > re.second=(pa*CBD+pb*CAD)/(CAD+CBD); > > return re; > > } > > pair<bool,Vec> getbanana(const Seg &la,const Seg &lb){ > > return getbanana(la.p1,la.p2,lb.p1,lb.p2); > > } > > > > /* > > 角度弧度轉換器 > > 弧度沒單位 > > 2pi=360度 > > (2pi是弧度) > > 同理,pi=180度 > > 1=180/pi度 > > pi/180=1度 > > */ > > double deg_rad(double angle){//角度轉弧度 > > return angle*M_PI/180; > > } > > double rad_deg(double angle){//弧度轉角度 > > return angle*180/M_PI; > > } > > > > Vec abs(Vec P){//對向量取絕對值 > > P.x=fabs(P.x); > > P.y=fabs(P.y); > > return P; > > } > > double lng(Vec P){ > > P=abs(P); > > return sqrt(P.x*P.x+P.y*P.y); > > } > > > > /* > > 點到線段距離 > > 考慮下面幾種情況 > > C > > A-B > > 我們可以知道角BAC是鈍角時,C和AB的最短距離就是CA > > 同理,當ABC為鈍角時,答案即為BC > > */ > > double Pnt_to_Lne(const Vec &P,const Vec &A,const Vec &B){//計算點到線最近距離 > > int BAP=sign((B-A)*(P-A)); > > int ABP=sign((A-B)*(P-B)); > > if(sign(lng(A-B))==0)return lng(P-A);//如果A==B > > if(BAP>=0 && ABP>=0){ > > return fabs(((A-P)^(B-P))/lng(A-B)); > > }else return lng(min(abs(A-P),abs(B-P))); > > } > > double Pnt_to_Lne(const Vec &P,const Seg la){ > > return Pnt_to_Lne(P,la.p1,la.p2); > > } > > > > bool sorta(Vec a,Vec b){//先以x降序排序,再以y升序排序 > > if(a.x==b.x)return a.y>b.y; > > else return a.x<b.x; > > } > > bool sortb(Vec a,Vec b){//先以x升序排序,再以y降序排序 > > if(a.x==b.x)return a.y<b.y; > > else return a.x>b.x; > > } > > > > Polygon convex(Polygon Pol){ > > Polygon re; > > sort(Pol.vec.begin(),Pol.vec.end(),sorta); > > re.vec.push_back(Pol.vec[0]); > > long long int n=Pol.vec.size(); > > for(INT i=1;i<n;i++){ > > if(re.vec.empty()){ > > re.push_back(Pol.vec[i]); > > continue; > > }else if(re.vec.back()==Pol.vec[i]){ > > continue; > > } > > while(re.vec.empty() || ori(re.vec.back(),*(re.vec.end()-1),Pol.vec[i])>=0){ > > re.vec.pop_back(); > > } > > re.vec.push_back(Pol.vec[i]); > > } > > sort(Pol.vec.begin(),Pol.vec.end(),sortb); > > for(INT i=0;i<n;i++){ > > if(re.vec.empty()){ > > re.vec.push_back(Pol.vec[i]); > > continue; > > }else if(re.vec.back()==Pol.vec[i]){ > > continue; > > } > > while(re.vec.empty() || ori(re.vec.back(),*(re.vec.end()-1),Pol.vec[i])>=0){ > > re.vec.pop_back(); > > } > > re.push_back(Pol.vec[i]); > > } > > return re; > > } > > > > int main(){ > > /*cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > INT t=read(INT); > > while(t--){ > > }*/ > > if(0){//測試Area > > Polygon Pol; > > Pol.push_back(1,2); > > Pol.push_back(1,3); > > Pol.push_back(2,1); > > cout<<Area(Pol)<<endl; > > } > > if(0){//測試sign > > cout<<sign(-1e-9)<<endl; > > cout<<sign(1e-9)<<endl; > > cout<<sign(-1e-10)<<endl;//誤差值內都會算做0 > > } > > if(0){//測試ori > > Vec O=make_Vec(0,0); > > Vec A=make_Vec(5,0); > > Vec B=make_Vec(-5,0); > > cout<<ori(O,A,B)<<endl;//1為逆時針,-1為順時針,0為同向or 180 > > } > > if(0){//測試btw > > Vec A=make_Vec(3,6); > > Vec B=make_Vec(7,8); > > Vec C=make_Vec(5,8); > > Seg Lne=make_Seg(A,B); > > if(btw(Lne,C)){ > > cout<<"True"<<endl; > > }else{ > > cout<<"False"<<endl; > > } > > } > > if(0){//測試banana > > Vec A=make_Vec(-1,3); > > Vec B=make_Vec(-5,4); > > Vec C=make_Vec(1,4); > > Vec D=make_Vec(5,2); > > Seg L1=make_Seg(A,B); > > Seg L2=make_Seg(C,D); > > pair<bool,Vec> re=getbanana(L1,L2); > > if(re.first){ > > cout<<"Banana is:("<<re.second.x<<","<<re.second.y<<")"<<endl; > > }else{ > > cout<<"No Banana"<<endl; > > } > > } > > if(0){//測試Pnt_to_Lne > > Vec P=make_Vec(-4,4); > > Vec A=make_Vec(-4,1); > > Vec B=make_Vec(-5,4); > > Seg L1=make_Seg(A,B); > > cout<<Pnt_to_Lne(P,L1)<<endl; > > } > > if(1){//測試convex > > Polygon pol; > > while(true){ > > cout<<"enter point> "; > > long long int xx,yy; > > cin>>xx>>yy; > > if(xx==0 && yy==0)break; > > pol.vec.push_back(make_Vec(xx,yy)); > > } > > cout<<"counting"<<endl; > > Polygon ans=convex(pol); > > cout<<"ans:"<<endl; > > for(Vec i:ans.vec){ > > cout<<"("<<i.x<<","<<i.y<<")"<<endl; > > } > > } > > return 0; > > } > > ``` > string > > `z_value.cpp` > > ```c++= > > /* > > 字串S[0:N-1]的Z-value > > Z[i]=( 最大的K滿足S[0:K-1]=S[i:i+k-1] ) > > 假設Z[i]值為n > > */ > > vector<INT> z_value(string s){ > > INT n=s.size(); > > INT l=0,r=0; > > vector<INT> z(n); > > for(INT i=1;i<n;i++){ > > if(i<=r){ > > z[i]=min(z[i-l],r-i+1); > > } > > while( > > i+z[i]<n && > > s[z[i]]==s[i+z[i]] > > )z[i]++; > > if(i+z[i]-1>r){ > > l=i,r=z[i]+i-1; > > } > > } > > return z; > > } > > > > int main(){ > > cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > int t=read(int); > > while(t--){ > > string str=read(string); > > vector<INT> z=z_value(str); > > for(INT i:z){ > > cout<<i<<" "; > > } > > cout<<endl; > > } > > return 0; > > } > > `trie.cpp` > > ```c++= > > struct trie{ > > trie* c[26]; > > INT cnt; > > trie(): cnt(0){ > > memset(c,0,sizeof(c)); > > } > > } > > > > INT cha_int(char c){ > > return c-'a'; > > } > > > > void insert(char *ca,trie *root){ > > while(*c){ > > if(!(*root).c[cha_int(*ca)]){ > > (*root).c[cha_int(*ca)]=new trie(); > > } > > root=(*root).c[cha_int(*ca)]; > > ca++; > > } > > (*root).cnt++; > > } > > > > int main(){ > > cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > int t=read(int); > > while(t--){ > > } > > return 0; > > } > > ``` > > `KMP.cpp` > > ```c++= > > vector<INT> getF(string str){ > > INT n=str.size(); > > vector<INT> re(n,-1); > > for(INT i=1;i<n;i++){ > > if(re[i-1]==-1){//上一個位置沒找到F值 > > if(str[i]==str[0]){ > > re[i]=0; > > }else{ > > re[i]=-1; > > } > > }else{ > > INT k=re[i-1]+1; > > re[i]=k; > > while(k>=0 && str[k]!=str[i]){ > > k=re[k]; > > re[i]=k; > > } > > } > > } > > return re; > > } > > > > vector<INT> KMS(string s,string t){ > > vector<INT> f=getF(s); > > INT ss=s.size(); > > INT ts=t.size(); > > vector<INT> re; > > INT p=-1;//表s的開頭要在t的哪裡 > > for(INT i=0;i<ts;i++){ > > while(p>=0 && s[p+1]!=t[i]){//重複移動p直到字元配對成功 > > p=f[p]; > > } > > if(s[p+1]==t[i]){ > > p++; > > } > > if(p+1==ss){ > > re.push_back(i-p); > > p=f[p]; > > } > > } > > return re; > > } > > > > int main(){ > > cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > int t=read(int); > > while(t--){ > > string s,t; > > cin>>s>>t; > > vector<INT> vec=KMS(s,t); > > for(INT i:vec){ > > cout<<i<<" "; > > } > > cout<<"end"<<endl; > > } > > return 0; > > } > > //#endif > > ``` > > `Failure.cpp` > > ```c++= > > > > vector<INT> getF(string str){ > > INT n=str.size(); > > vector<INT> re(n,-1); > > for(INT i=1;i<n;i++){ > > if(re[i-1]==-1){ > > if(str[i]==str[0]){ > > re[i]=0; > > }else{ > > re[i]=-1; > > } > > }else{ > > INT k=re[i-1]+1; > > re[i]=k; > > while(k>=0 && str[k]!=str[i]){ > > k=re[k]; > > re[i]=k; > > } > > } > > } > > return re; > > } > > > > int main(){ > > cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > int t=read(int); > > while(t--){ > > string s; > > cin>>s; > > vector<INT> vec=getF(s); > > for(INT i:vec){ > > cout<<i<<" "; > > } > > cout<<endl; > > } > > return 0; > > } > > //#endif > > ``` > > > tree > > `lca.cpp` > > ```c++= > > /* > > [LCA]最近共同祖先 > > [參考資料]https://yuihuang.com/lowest-common-ancestor/ > > */ > > > > const INT mxn=1e5; > > > > INT dep[mxn];//距離根節點的距離(根節點距離為1) > > INT siz[mxn];//子樹節點數(包含自己) > > INT p[mxn][35];//p[i][j]表i的第2^i祖先 > > vector<INT> v[mxn]; > > > > int dfs(int node=0 , int d){//計算深度及子樹節點數 > > dep[node] = d + 1;//深度 > > if (v[node].empty()){//如果沒有子節點 > > siz[node] = 1; > > return 1; > > } > > int total = 1;//自己也是一個節點 > > for (int i:v[node]){ > > total += dfs(i, d+1); > > } > > siz[node] = total; > > return siz[node]; > > } > > > > void build(INT n){//註1 > > // 找出每個節點的 2^i 倍祖先 > > // 2^20 = 1e6 > 200000 > > for (int i = 1; i < 20; i++){ > > for (int j = 1; j <= n; j++){ > > p[j][i] = p[p[j][i-1]][i-1]; > > } > > } > > } > > > > > > int lca(int a, int b){// 求a和b的LCA(利用倍增法) > > if (dep[b] < dep[a]) swap(a, b); > > if (dep[a] != dep[b]){//確保dep是相同的 > > int dif = dep[b] - dep[a]; > > for (int i = 0; i < 20; i++){//註2 > > if (dif & 1) b = p[b][i]; > > dif >>= 1; > > } > > } > > if (a == b) return a;//如果位置相同,那lca就是自己 > > for (int i = 19; i >= 0; i--){//註3 > > if (p[a][i] != p[b][i]){ > > a = p[a][i]; > > b = p[b][i]; > > } > > } > > return p[a][0]; > > } > > > > > > int main(){ > > cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > return 0; > > } > > ``` > > `rmq.cpp` > > ```c++= > > //區間最大值 > > const INT mxn=500000; > > INT zipnum=600; > > INT n; > > INT origlst[mxn+1]; > > INT ziplst[mxn+1]; > > int main(){ > > cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > while(cin>>n){ > > zipnum=sqrt(n); > > for(INT i=0;i<n;i++){ > > cin>>origlst[i]; > > if(i%zipnum==0){ > > ziplst[i/zipnum]=origlst[i]; > > }else{ > > ziplst[i/zipnum]=max(ziplst[i/zipnum],origlst[i]); > > } > > } > > INT q; > > cin>>q; > > while(q--){ > > INT l,r; > > cin>>l>>r; > > l--; > > r--; > > if(l>r)swap(l,r); > > INT ans=origlst[l]; > > while(l%zipnum && l<=r){ > > ans=max(ans,origlst[l]); > > l++; > > } > > while((l+zipnum)<r){ > > ans=max(ans,ziplst[l/zipnum]); > > l+=zipnum; > > } > > while(l<=r){ > > ans=max(ans,origlst[l]); > > l++; > > } > > cout<<ans<<endl; > > } > > } > > return 0; > > } > > ``` > > `dijkstra.cpp` > > ```c++= > > /* > > [q]https://neoj.sprout.tw/problem/391/ > > [AC] > > [求最短路] > > int main(){ > > cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > INT t=read(int); > > while(t--){ > > INT N,M,S,E,F;//輸入點數量,起點,終點 > > cin>>N>>M>>S>>E>>F; > > INT lst[N+1];//紀錄S到i點的最近距離 > > vector<pair<INT,INT>> edge[N+1]; > > fill(lst,lst+N+1,1e16); > > bool visit[N+1]; > > memset(visit,0,sizeof(visit)); > > > > for(INT i=0;i<M;i++){//輸入點資訊 > > INT A,B,C,D,C2; > > cin>>A>>B>>C>>D>>C2; > > INT V=min(F,D)*C+max((INT)0,F-D)*C2; > > edge[A].push_back(make_pair(B,V)); > > } > > > > //do Dijkstra > > > > priority_queue<PII,vector<PII>,greater<PII>> pq;//將點以距離(對點1)排序 > > pq.push(make_pair(0,S)); > > lst[S]=0; > > > > while(!pq.empty()){ > > INT nw=pq.top().second; > > pq.pop(); > > if(visit[nw])continue;//如果那個點作過了,就不要再做一次了 > > //可以證明每個點作的第一次都是最好的一次,之後就沒有了 > > > > for(PII i:edge[nw]){ > > INT nxt=i.first,V=i.second; > > if(lst[nw]+V<lst[nxt]){//發現更短的距離 > > lst[nxt]=lst[nw]+V; > > pq.push(make_pair(lst[nxt],nxt)); > > } > > } > > visit[nw]=1; > > } > > cout<<lst[E]<<endl; > > } > > return 0; > > } > > `最短路徑.cpp` > > ```c++= > > /* > > [zj] [Q]https://zerojudge.tw/ShowProblem?problemid=c128 > > [AC] > > [最短路徑] > > 這一題是在找 > > 找出一條路 > > 再找出這條路經過的數的最小值 > > 盡可能讓這個值最大 > > 該值即為所求 > > */ > > /*num*/ > > bool debug=false; > > bool iofast=true; > > string s1,s2; > > INT n,r; > > INT id=1; > > map<string,INT>stint; > > const INT maxn=200; > > INT mp[maxn+1][maxn+1]; > > INT season=0; > > INT num1,num2; > > INT h; > > /*fn定義*/ > > INT find(string str){ > > if(stint[str]==0){ > > stint[str]=id; > > id++; > > return stint[str]; > > }else return stint[str]; > > } > > /*main*/ > > int main(){ > > /*IO加速*/ > > if(!debug&&iofast)what_the_fuck; > > while(cin>>n>>r){ > > if(n==0&&r==0)break; > > /*re:0*/ > > season++; > > stint.clear(); > > s1.clear(); > > s2.clear(); > > id=1; > > num1=0; > > num2=0; > > h=0; > > for(INT i=0;i<=n;i++){ > > for(INT j=0;j<=n;j++){ > > mp[i][j]=-1; > > } > > } > > /*CIN*/ > > for(INT i=0;i<r;i++){ > > cin>>s1>>s2>>h; > > num1=find(s1); > > num2=find(s2); > > mp[num1][num2]=h; > > mp[num2][num1]=h; > > } > > cin>>s1>>s2; > > num1=find(s1); > > num2=find(s2); > > /*solve*/ > > for(INT i=1;i<=n;i++){//中繼站 > > for(INT j=1;j<=n;j++){//起點(或終點) > > for(INT k=j+1;k<=n;k++){//終點(或起點) > > INT tosen=min(mp[j][i],mp[i][k]);//j=>i=>k > > mp[j][k]=max(mp[j][k],tosen);//j=>k或者上面的,看哪個載重量比較大 > > mp[k][j]=mp[j][k]; > > } > > } > > } > > cout<<"Scenario #"<<season<<endl; > > cout<<mp[num1][num2]<<" tons"<<endl<<endl; > > } > > return 0; > > } > > ``` > > `最短路徑-greedy.cpp` > > ```c++= > > const INT mxn=1e5; > > INT ans=0; > > vector<PII> tre[mxn+1],bktre[mxn+1];//tre[起點][i]={終點,花費} > > INT n,m; > > INT lne[mxn+1]; > > > > /*main*/ > > int main(){ > > if(!debug&&iofast){what_the_fuck;} > > srand(time(NULL)); > > while(cin>>n>>m){ > > for(INT i=0;i<=n;i++){ > > tre[i].clear(); > > bktre[i].clear(); > > } > > for(INT i=0;i<=n;i++){ > > lne[i]=1000000000; > > } > > ans=0; > > /*CIN*/ > > for(INT i=0;i<m;i++){ > > INT a,b,c; > > cin>>a>>b>>c; > > tre[a].push_back({b,c}); > > bktre[b].push_back({a,c}); > > } > > /*solve*/ > > //出去 > > priority_queue<PII,vector<PII>,greater<PII>>que;//目前路徑最小的會先被拉出來 > > que.push({0,1});//{目前花費,位置} > > lne[1]=0; > > while(que.wassomething()){ > > PII nw=que.top(); > > que.pop(); > > if(lne[nw.SEC]!=nw.FIR)continue;//如果紀錄的和現在的不一樣就跳出(根據bfs的特性,跑過的地方數值絕對比較小) > > ans+=lne[nw.SEC]; > > for(PII i:tre[nw.SEC]){ > > if(lne[i.FIR]>lne[nw.SEC]+i.SEC){//如果從這邊走過去會比原本的方案好,那就加進去 > > lne[i.FIR]=lne[nw.SEC]+i.SEC; > > que.push({lne[i.FIR],i.FIR}); > > } > > } > > } > > //回來 > > for(INT i=0;i<=n;i++){ > > lne[i]=1000000000; > > } > > lne[1]=0; > > que.push({0,1}); > > while(que.wassomething()){ > > PII nw=que.top(); > > que.pop(); > > if(lne[nw.SEC]!=nw.FIR)continue; > > ans+=lne[nw.SEC]; > > for(PII i:bktre[nw.SEC]){ > > if(lne[i.FIR]>lne[nw.SEC]+i.SEC){ > > lne[i.FIR]=lne[nw.SEC]+i.SEC; > > que.push({lne[i.FIR],i.FIR}); > > } > > } > > } > > cout<<ans<<endl; > > } > > return 0; > > } > > ``` > > `最短路徑dfs.cpp` > > ```c++= > > vector<PII> tre[27]; > > INT ans=0; > > /*fn定義*/ > > INT dfs(INT p,INT g){ > > ans=max(ans,g); > > for(auto i:(tre[p])){ > > dfs(i.first,g+i.second); > > } > > return 0; > > } > > /*main*/ > > int main(){ > > {/*IO加速*/ > > cin.tie(0); > > cout.tie(0); > > ios::sync_with_stdio(false); > > } > > /*CIN*/ > > char c; > > cin>>c; > > INT st=c-'A'; > > INT n; > > cin>>n; > > for(INT i=0;i<n;i++){ > > char a,b; > > INT g; > > cin>>a>>b>>g; > > INT ia=a-'A',ib=b-'A'; > > tre[ia].push_back({ib,g}); > > } > > /*solve*/ > > dfs(st,0); > > cout<<ans<<"\n"; > > return 0; > > } > > ``` > > `BIT.cpp` > > ```c++= > > INT n; > > vector<INT> vec; > > vector<INT> BIT; > > > > INT low_bit(INT x){ > > return x&(-x); > > } > > > > INT getsum(INT x){//求1~x的值 > > INT re=0; > > while(x>0){ > > re+=BIT[x]; > > x-=low_bit(x); > > } > > return re; > > } > > > > void update(INT x){//單點加1 > > while(x<=n){ > > BIT[x]+=1; > > x+=low_bit(x); > > } > > } > > > > int main(){ > > cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > INT t=read(int); > > while(t--){ > > cin>>n; > > vec.clear(); > > BIT.clear(); > > vec.resize(n+1); > > BIT.resize(n+1); > > for(INT i=1;i<=n;i++){ > > cin>>vec[i]; > > } > > INT ans=0; > > for(INT i=n;i>=1;i--){ > > ans+=getsum(vec[i]); > > update(vec[i]); > > } > > cout<<ans<<endl; > > > > DBG{ > > cerr<<"DBG "; > > for(INT i=1;i<=n;i++){ > > cerr<<BIT[i]<<" "; > > } > > cerr<<endl; > > } > > } > > return 0; > > } > > ``` > > `dsu.cpp` > > ```c++= > > struct dsu{ > > vector<INT> vec;//vec[i]紀錄i連到哪裡 > > vector<set<INT>> se;//se[i]記錄所有連到i的點編號 > > void init(INT n){//初始化 > > se.clear(); > > se.resize(n+1); > > vec.clear(); > > vec.resize(n+1); > > for(INT i=0;i<=n;i++){ > > vec[i]=i; > > se[i].clear(); > > } > > } > > INT find(INT n){//查詢編號 > > if(vec[n]==n){ > > return n; > > }else{ > > INT re=find(vec[n]);//找出最終老大 > > se[vec[n]].erase(n);//將n連到re,所以要把vec[n]的被動連線解除掉 > > vec[n]=re;//將n連到re > > se[re].insert(n);//re被n連 > > return re; > > } > > } > > void merge(INT a,INT b){//合併兩者 > > INT aboss=find(a); > > INT bboss=find(b); > > vec[aboss]=bboss;//將a樹連到b樹 > > se[bboss].insert(aboss);//b樹被a連 > > } > > void erase(INT n){//將n孤立 > > vec[n]=n;//將自己連到自己 > > INT othboss=*(se[n].begin());//其他的老大就用第一個連到n的人來當 > > for(INT i:se[n]){ > > vec[i]=othboss; > > se[othboss].insert(i); > > } > > se[n].clear(); > > } > > }; > > ``` > > `seg_tree.cpp` > > ```c++= > > /* > > [q] > > [] > > */ > > //#ifndef eval > > #include<bits/stdc++.h> > > using namespace std; > > #define INT long long int > > #define endl "\n" > > #define read(n) reader<n>() > > #define DBG if(debug) > > bool debug=0; > > template<typename tpe>tpe reader(){ > > tpe re;cin>>re;return re; > > } > > > > vector<INT> vec; > > vector<INT> seg_tree; > > INT n; > > INT build(INT l,INT r,INT p=1){//將vec建成seg_tree > > if(l==r){ > > seg_tree[p]=vec[l]; > > }else{ > > INT mnt=(l+r)/2; > > INT lp=build(l,mnt,p<<1); > > INT rp=build(mnt+1,r,p<<1|1); > > seg_tree[p]=lp+rp; > > } > > return seg_tree[p]; > > } > > > > void call_build(INT n){ > > build(0,n); > > } > > > > INT edit(INT e,INT v,INT l,INT r,INT p=1){//單點編輯 > > if(l==r){ > > if(l==e){ > > vec[e]=v; > > seg_tree[p]=v; > > } > > }else{ > > INT mnt=(l+r)/2; > > INT lp=edit(e,v,l,mnt,p<<1); > > INT rp=edit(e,v,mnt+1,r,p<<1|1); > > seg_tree[p]=lp+rp; > > } > > return seg_tree[p]; > > } > > > > void call_edit(INT e,INT v,INT n){ > > edit(e,v,0,n); > > } > > > > bool invs(INT la,INT ra,INT lb,INT rb){//檢測兩區間是否有重疊 > > INT l=max(la,lb); > > INT r=min(ra,rb); > > return l<=r; > > } > > > > INT search(INT sl,INT sr,INT l,INT r,INT p=1){//求區間和 > > if(sl<l)sl=l; > > if(r<sr)sr=r; > > if(sl==l && sr==r && l<=r){ > > return seg_tree[p]; > > }else{ > > INT mnt=(l+r)/2; > > bool lbl=invs(l,mnt,sl,sr); > > bool rbl=invs(mnt+1,r,sl,sr); > > if(lbl && rbl){ > > INT l=search(sl,sr,l,mnt,p<<1); > > INT r=search(sl,sr,mnt+1,r,p<<1|1); > > return l+r; > > }else if(lbl){ > > INT l=search(sl,sr,l,mnt,p<<1); > > return l; > > }else if(rbl){ > > INT r=search(sl,sr,mnt+1,r,p<<1|1); > > return r; > > }else{ > > return 0; > > } > > } > > } > > > > INT call_search(INT sl,INT sr,INT n){ > > return search(sl,sr,0,n); > > } > > > > int main(){ > > cin.tie(0);cout.tie(0);ios::sync_with_stdio(0); > > INT t=1; > > while(t--){ > > n=read(INT); > > vec.resize(n); > > seg_tree.resize(n*4); > > for(INT i=0;i<n;i++){ > > vec[i]=read(INT); > > } > > n--; > > call_build(n); > > > > INT m=read(INT); > > while(m--){ > > INT doid=read(INT); > > if(doid==1){ > > INT e,v; > > cin>>e>>v; > > call_edit(e,v,n); > > }else{ > > INT l,r; > > cin>>l>>r; > > cout<<call_search(l,r,n)<<endl; > > } > > } > > } > > return 0; > > } > > //#endif > > ```