1、凸包(最大三角形)
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <cmath>using namespace std;#define eps 1e-8struct node{int x,y;};node p[50005];node res[50005];int cross(node p0,node p1,node p2){return (p0.x*p1.y-p1.x*p0.y)+(p1.x*p2.y-p2.x*p1.y)+(p2.x*p0.y-p0.x*p2.y);}bool cmp(node a,node b){if(a.x==b.x)return a.y<b.y;elsereturn a.x<b.x;}int Graham(int n){int len;int top=0;sort(p,p+n,cmp);for(int i=0; i<n; i++){while(top>1&&cross(res[top-1],p[i],res[top-2])<=0)top--;res[top++]=p[i];}len=top;for(int i=n-2; i>=0; i--){while(top>len&&cross(res[top-1],p[i],res[top-2])<=0) //如果新增的点与前两点够不成凸型,则把上一点删去top--;res[top++]=p[i];}if(n>1)top--;return top;}int main(){int n;while(cin>>n){for(int i=0; i<n; i++)cin>>p[i].x>>p[i].y;int dian=Graham(n);int ans=-22;for(int i=0; i<dian; i++)for(int j=i+1; j<dian; j++)for(int k=j+1; k<dian; k++)ans=max(ans,cross(res[j],res[k],res[i]));printf("%.2lf\n",0.5*ans);}return 0;}
2、稳定凸包
struct node{int x,y;} str[2005],res[2005];int dis(node a,node b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}int cross(node p1,node p2,node p3){return (p1.x*p2.y-p1.y*p2.x)+(p2.x*p3.y-p2.y*p3.x)+(p3.x*p1.y-p3.y*p1.x);}bool cmp(node a,node b){if(cross(str[0],a,b)>0) return 1;//不共线else if(cross(str[0],a,b)==0&&dis(str[0],a)<dis(str[0],b)) return 1;//共线选距离短的return 0;}void tubao(int n){int top=1;sort(str,str+n,cmp1);res[0]=str[0];res[1]=str[1];for(int i=2;i<n;i++){while(top && cross(str[i],res[top],res[top-1])>0)top--;res[++top]=str[i];}int len=top;res[++top]=str[n-2];for(int i=n-3;i>=0;i--){while(top!=len &&cross(str[i],res[top],res[top-1])>0)top--;res[++top]=str[i];}return --top;}int judge(){for(int i=1; i<top; i++)if(cross(arr[i],arr[i-1],arr[i+1])!=0&&cross(arr[i],arr[i+2],arr[i+1])!=0) return 0;//判断三点共线return 1;}int main(){int n,m;int t;cin>>t;while(t--){cin>>n;for(int i=0; i<n; i++){cin>>str[i].x>>str[i].y;}int pos=0;for(int i=1; i<n; i++){if((str[i].x<str[pos].x)||(str[i].x==str[pos].x&&str[i].y<str[pos].y))//选出最优顶点pos=i;}swap(str[0],str[pos]);tubao(n);if(judge()&&n>=6)cout<<"YES"<<endl;elsecout<<"NO"<<endl;}return 0;}
3、pick定理
//在网格中计算两点连线上的点个数:gcd(abs(x1-x2),abs(y1-y2));//Pick定理:s=in+out/2-1;struct node{int x,y;} str[105];int gcd(int n,int m){if(m==0)return n;elsereturn gcd(m,n%m);}int cross(node p1,node p2){return p1.x*p2.y-p1.y*p2.x;}int main(){int flag=1;int t;int m;cin>>t;while(t--){cin>>m;int x,y;str[0].x=0,str[0].y=0;for(int i=1; i<=m; i++){cin>>x>>y;str[i].x=str[i-1].x+x;str[i].y=str[i-1].y+y;}int area=0;int out=0;int in=0;for(int i=1; i<m; i++){area+=cross(str[i],str[i+1]);//差积计算面积out+=gcd(abs(str[i].x-str[i+1].x),abs(str[i].y-str[i+1].y));}area += cross(str[m], str[1]);out += gcd(abs(str[m].x - str[1].x), abs(str[m].y - str[1].y));if(area<0)area=-area;in=area+2-out;in/=2;cout<<"Scenario #"<<flag++<<":"<<endl;if(area%2==0){printf("%d %d %d.0\n\n",in,out,area/2);}else{printf("%d %d %d.5\n\n",in,out,area/2);}}return 0;}
4、旋转卡壳算法
const int maxl=2000+10;struct node{double x,y;}str[maxl],res[maxl];double dis(node a,node b){return (double)sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}bool cmp(node a,node b){if(a.x==b.x)return a.y<b.y;return a.x<b.x;}double cross(node a,node b,node c){return (a.x*b.y-a.y*b.x)+(b.x*c.y-b.y*c.x)+(c.x*a.y-c.y*a.x);}int tubao(int n){sort(str,str+n,cmp);int len;int top=0;for(int i=0;i<n;i++){while(top>1&&cross(res[top-1],str[i],res[top-2])<=0)top--;res[top++]=str[i];}len=top;for(int i=n-2;i>=0;i--){while(top>len&&cross(res[top-1],str[i],res[top-2])<=0)top--;res[top++]=str[i];}if(n>1)top--;return top;}int main(){int n;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%lf%lf",&str[i].x,&str[i].y);}int ans=tubao(n);double sum=0;for(int i=0;i<ans-2;i++){int ti=(i+3)%ans,tj=(i+1)%ans;for(int j=i+2;j<ans;j++){//对角线两边选一个点计算面积while(fabs(cross(res[i],res[j],res[ti]))<fabs(cross(res[i],res[j],res[(ti+1)%ans]))) ti=(ti+1)%ans;while(fabs(cross(res[i],res[j],res[tj])) < fabs(cross(res[i],res[j],res[(tj+1)%ans]))) tj=(tj+1)%ans;sum = max(sum, fabs(cross(res[i],res[j],res[ti]))+fabs(cross(res[i],res[j],res[tj])));//计算四边形最大面积}}printf("%.3lf\n",sum/2);return 0;}//输入信息int ans=tubao(n);int sum=0;int q=1;res[ans]=res[0];for(int p=0; p<ans; p++){while(cross(res[p+1],res[q],res[p])<cross(res[p+1],res[q+1],res[p]))q=(q+1)%ans;sum=max(sum,max(dis(res[p],res[q]),dis(res[p+1],res[q+1])));}printf("%d\n",sum);3、(分治)计算最短距离点对(nlogn)const int maxl=100000+10;const double inf=1e20;struct node{double x,y;} str[maxl],arr[maxl];double dist(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}//利用排序规则将点分为左右两部分bool cmp(node a,node b){if(a.x==b.x)return a.y<b.y;return a.x<b.x;}//把以中线为界左右一定范围的点进行排序bool cmp1(node a,node b){return a.y<b.y;}double clost(int left,int right){double d=inf;if(left==right){return d;}if(left+1==right){return dist(str[left],str[right]);}int mid=(left+right)/2;double d1=clost(left,mid);//再分为左边界double d2=clost(mid+1,right);//分为右边界d=min(d1,d2);//取两边界最小int k=0;//将分界线周围符合要求的点记录起来for(int i=left; i<=right; i++){if(fabs(str[mid].x-str[i].x)<=d){arr[k++]=str[i];}}sort(arr,arr+k,cmp1);//对分界线周围符合条件的点进行处理,更新dfor(int i=0; i<k; i++){for(int j=i+1; j<k&&arr[j].y-arr[i].y<d; j++){d=min(d,dist(arr[i],arr[j]));}}return d;}int main(){int n;while(cin>>n&&n){for(int i=0; i<n; i++){cin>>str[i].x>>str[i].y;}sort(str,str+n,cmp);printf("%.2lf\n",clost(0,n-1)/2);}return 0;}
5、半平面交
//in the counterclockwise order:逆时针//in clockwise order:顺时针//(多边形的核)#define exp 1e-8const int maxl = 210;int ccnt, zcnt;//ccnt为最终切割后得到多边形的顶点个数,zcnt暂存int m;struct point{double x, y;};point arr[maxl], p[maxl], q[maxl];void getline(point x, point y, double &a, double &b, double &c) //两点x、y确定一条直线a、b、c为其系数{a = y.y - x.y;b = x.x - y.x;c = y.x * x.y - x.x * y.y;}void initial(){for (int i = 1; i <= m; ++i)p[i] = arr[i];p[m + 1] = p[1];p[0] = p[m];ccnt = m;//ccnt为最终切割得到的多边形的顶点数,将其初始化为多边形的顶点的个数}point jiaodian(point x, point y, double a, double b, double c) //求x、y形成的直线与已知直线a、b、c、的交点{double u = fabs(a * x.x + b * x.y + c);double v = fabs(a * y.x + b * y.y + c);point pt;pt.x = (x.x * v + y.x * u) / (u + v);pt.y = (x.y * v + y.y * u) / (u + v);return pt;}void cut(double a, double b, double c){zcnt = 0;for (int i = 1; i <= ccnt; ++i){if (a*p[i].x + b * p[i].y + c >= 0)q[++zcnt] = p[i];// c由于精度问题,可能会偏小,所以有些点本应在右侧而没在,//故应该接着判断else{if (a*p[i - 1].x + b * p[i - 1].y + c > 0) //如果p[i-1]在直线的右侧的话,{//则将p[i],p[i-1]形成的直线与已知直线的交点作为核的一个顶点(这样的话,由于精度的问题,核的面积可能会有所减少)q[++zcnt] = jiaodian(p[i], p[i - 1], a, b, c);}if (a*p[i + 1].x + b * p[i + 1].y + c > 0) //原理同上{q[++zcnt] = jiaodian(p[i], p[i + 1], a, b, c);}}}for (int i = 1; i <= zcnt; ++i)p[i] = q[i];//将q中暂存的核的顶点转移到p中p[zcnt + 1] = q[1];p[0] = p[zcnt];ccnt = zcnt;}//判断面积大小int dcmp(double x){if (fabs(x) < exp) return 0;else return 1;}void solve(){//注意:默认点是顺时针,如果题目不是顺时针,规整化方向initial();for (int i = 1; i <= m; ++i){double a, b, c;getline(arr[i], arr[i + 1], a, b, c);cut(a, b, c);}//多边形核的面积double area = 0;for (int i = 1; i <= zcnt; ++i)area += p[i].x * p[i + 1].y - p[i + 1].x * p[i].y;area = fabs(area / 2.0);//面积为0,不存在核点if (!zcnt&&dcmp(area) == 0)puts("NO");elseputs("YES");}//如果输入点是顺时针则不用,如果是逆时针,则将点的方向发过来void GuiZhengHua(){//规整化方向,逆时针变顺时针,顺时针变逆时针for(int i = 1; i < (m+1)/2; i ++)swap(arr[i], arr[m-i]);}int main(){int t;cin >> t;while (t--){cin >> m;int i;for (i = 1; i <= m; i++)cin >> arr[i].x >> arr[i].y;arr[m + 1] = arr[1];solve();}return 0;}//求多边形中最大圆半径#include<iostream>#include<string.h>#include<algorithm>#include<cmath>#include<stdio.h>using namespace std;const int maxn=210;const double esp=1e-8;const int inf=1e9;int ccnt,zcnt;int m;struct node{double x,y;};node arr[maxn],p[maxn],q[maxn];void GetLine(node x,node y,double &a,double &b,double &c){a=y.y-x.y;b=x.x-y.x;c=y.x*x.y-x.x*y.y;}void initial(){for(int i=1; i<=m; i++) p[i]=arr[i];p[m+1]=p[1];p[0]=p[m];ccnt=m;}node jiaodian(node x,node y,double a,double b,double c){double u=fabs(a*x.x+b*x.y+c);double v=fabs(a*y.x+b*y.y+c);node pt;pt.x=(x.x*v+y.x*u)/(u+v);pt.y=(x.y*v+y.y*u)/(u+v);return pt;}void cut(double a,double b,double c){zcnt=0;for(int i=1; i<=ccnt; i++){if(a*p[i].x+b*p[i].y+c>=0) q[++zcnt]=p[i];else{if(a*p[i-1].x+b*p[i-1].y+c>0){q[++zcnt]=jiaodian(p[i],p[i-1],a,b,c);}if(a*p[i+1].x+b*p[i+1].y+c>0){q[++zcnt]=jiaodian(p[i],p[i+1],a,b,c);}}}for(int i=1; i<=zcnt; i++){p[i]=q[i];}p[zcnt+1]=q[1];p[0]=p[zcnt];ccnt=zcnt;}int dcmp(double x){if(fabs(x)<esp) return 0;return 1;}int solve(double r){initial();for(int i=1; i<=m; i++){node ta, tb, tt;//得到平移后的直线tt.x = arr[i + 1].y - arr[i].y;tt.y = arr[i].x - arr[i + 1].x;double k = r / sqrt(tt.x * tt.x + tt.y * tt.y);tt.x = tt.x * k;tt.y = tt.y * k;ta.x = arr[i].x + tt.x;ta.y = arr[i].y + tt.y;tb.x = arr[i + 1].x + tt.x;tb.y = arr[i + 1].y + tt.y;double a,b,c;GetLine(ta,tb,a,b,c);cut(a,b,c);}double area=0;for(int i=1; i<=zcnt; i++){area+=p[i].x*p[i+1].y-p[i+1].x*p[i].y;}area=fabs(area/2.0);if(!zcnt&&dcmp(area)==0){return 0;}else{return 1;}}void GuiZhengHua(){for(int i=1; i<(m+1)/2; i++){swap(arr[i],arr[m-i]);}}int main(){while(scanf("%d",&m)!=EOF){if(m==0) break;for(int i=1; i<=m; i++){cin>>arr[i].x>>arr[i].y;}GuiZhengHua();arr[m+1]=arr[1];double left=0,right=inf,mid;while((right-left)>=esp)//二分半径{mid=(right+left)/2.0;if(solve(mid)){left=mid;}else{right=mid;}}printf("%.6f\n", left);}return 0;}
6、求圆和矩形相交的面积
struct Point{double x,y;Point() {}Point(double xx,double yy){x=xx;y=yy;}Point operator -(Point s){return Point(x-s.x,y-s.y);}Point operator +(Point s){return Point(x+s.x,y+s.y);}double operator *(Point s){return x*s.x+y*s.y;}double operator ^(Point s){return x*s.y-y*s.x;}} p[M];double len(Point a){return sqrt(a*a);}double dis(Point a,Point b){return len(b-a);}double cross(Point a,Point b,Point c){return (b-a)^(c-a);}double dot(Point a,Point b,Point c){return (b-a)*(c-a);}double area(Point b,Point c,double r){Point a(0.0,0.0);if(dis(b,c)<eps) return 0.0;double h=fabs(cross(a,b,c))/dis(b,c);if(dis(a,b)>r-eps&&dis(a,c)>r-eps){double angle=acos(dot(a,b,c)/dis(a,b)/dis(a,c));if(h>r-eps) return 0.5*r*r*angle;else if(dot(b,a,c)>0&&dot(c,a,b)>0){double angle1=2*acos(h/r);return 0.5*r*r*fabs(angle-angle1)+0.5*r*r*sin(angle1);}else return 0.5*r*r*angle;}else if(dis(a,b)<r+eps&&dis(a,c)<r+eps) return 0.5*fabs(cross(a,b,c));else{if(dis(a,b)>dis(a,c)) swap(b,c);if(fabs(dis(a,b))<eps) return 0.0;if(dot(b,a,c)<eps){double angle1=acos(h/dis(a,b));double angle2=acos(h/r)-angle1;double angle3=acos(h/dis(a,c))-acos(h/r);return 0.5*dis(a,b)*r*sin(angle2)+0.5*r*r*angle3;}else{double angle1=acos(h/dis(a,b));double angle2=acos(h/r);double angle3=acos(h/dis(a,c))-angle2;return 0.5*r*dis(a,b)*sin(angle1+angle2)+0.5*r*r*angle3;}}}int main(){int T,n=4;double rx,ry,R;scanf("%lf%lf%lf",&rx,&ry,&R);scanf("%lf%lf%lf%lf",&p[1].x,&p[1].y,&p[3].x,&p[3].y);p[2].x=p[1].x; p[2].y=p[3].y; p[4].x=p[3].x; p[4].y=p[1].y;p[5]=p[1];Point O(rx,ry);for (int i=1; i<=n+1; i++) p[i]=p[i]-O;O=Point(0,0);double sum=0;for (int i=1; i<=n; i++){int j=i+1;double s=area(p[i],p[j],R);if (cross(O,p[i],p[j])>0) sum+=s;else sum-=s;}printf("%.4lf\n",fabs(sum));return 0;}
7、判断直线是否和圆相交(在圆内部也算)
bool judge(node a,node b){if( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) -b.r*b.r<=esp)return 1;return 0;}bool Judis(node P1,node P2,node o){if(judge(P1,o)&&judge(P2,o))return true;//如果只判断与圆相交不包含在内部就返回false,因为这是判断两个点都在圆内部if(!judge(P1,o)&&judge(P2,o)||judge(P1,o)&&!judge(P2,o))return true;double A,B,C,dist1,dist2,angle1,angle2;if(P1.x==P2.x)A=1,B=0,C= -P1.x;else if(P1.y==P2.y)A=0,B=1,C= -P1.y;else{A = P1.y-P2.y;B = P2.x-P1.x;C = P1.x*P2.y - P1.y*P2.x;}dist1 = A *o.x + B * o.y + C;dist1 *= dist1;dist2 = (A * A + B * B) * o.r * o.r;if (dist1 >dist2) return false;angle1 = (o.x- P1.x) * (P2.x - P1.x) + (o.y - P1.y) * (P2.y - P1.y);angle2 = (o.x - P2.x) * (P1.x - P2.x) + (o.y - P2.y) * (P1.y - P2.y);if (angle1 >0 && angle2 > 0) return true;return false;}
8、圆和正方形相交,相离
//相交://a:正方形四个点在圆内(不在圆上)//b:圆的五点在正方形内(不在正方形边上)(五点是指圆心加上圆的最上下左右四个点,还有正方形四个点都在圆上的情况,这时候要用圆心判断)//相接触://就是上面a,b,中的不在圆上不在正方形边上的条件去掉。//相离://其余就是相离的情况#include <bits/stdc++.h>using namespace std;typedef long long ll;const double eps=1e-8;const double PI= acos(-1.0);const int M = 1e5+7;struct node{double x,y;};node c,t;double r,s;double dis(node a,node b){return ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}int in_cir(node p)//点p是否在圆内2,是否在圆上1,否则0{double d=dis(p,c);if(d<r*r)return 2;if(d==r*r)return 1;return 0;}int in_square(node p)//点p是否在正方形内2,是否在正方形边上1,否则0{if(p.x>t.x&&p.x<t.x+s&&p.y>t.y&&p.y<t.y+s)return 2;else if(p.x==t.x&&p.y>=t.y&&p.y<=t.y+s)return 1;else if(p.x==t.x+s&&p.y>=t.y&&p.y<=t.y+s)return 1;else if(p.y==t.y&&p.x>=t.x&&p.x<=t.x+s)return 1;else if(p.y==t.y+s&&p.x>=t.x&&p.x<=t.x+s)return 1;elsereturn 0;}int main(){ios::sync_with_stdio(false);cin.tie(0);cin>>c.x>>c.y>>r;cin>>t.x>>t.y>>s;int f=-1;if(in_cir(t)==2||in_cir(node{t.x+s,t.y})==2||in_cir(node{t.x,t.y+s})==2||in_cir(node{t.x+s,t.y+s})==2)f=2;//正方形顶点在圆内else if(in_square(node{c.x-r,c.y})==2||in_square(node{c.x+r,c.y})==2||in_square(node{c.x,c.y+r})==2||in_square(node{c.x,c.y-r})==2||in_square(c)==2)f=2;//圆的5点在正方形内else{int nm1=0,nm2=0;if(in_cir(t)==1)nm1++;if(in_cir(node{t.x+s,t.y})==1)nm1++;if(in_cir(node{t.x,t.y+s})==1)nm1++;if(in_cir(node{t.x+s,t.y+s})==1)nm1++;if(in_square(node{c.x-r,c.y})==1) nm2++;if(in_square(node{c.x+r,c.y})==1)nm2++;if(in_square(node{c.x,c.y+r})==1)nm2++;if(in_square(node{c.x,c.y-r})==1)nm2++;if(nm1==1||nm2==1)f=1;else f=0;}cout<<f<<endl;return 0;}
9、运算符重载
const double EPS = 1e-10;// 浮点数的符号int sgn(double f){if(f < -EPS)return -1;if(f > EPS)return 1;return 0;}// 点、向量typedef struct pnt // point{double x, y;pnt(double _x = 0.0, double _y = 0.0):x(_x), y(_y) {}// 判相等bool operator == (const pnt &rhs) const{return !sgn(x - rhs.x) && !sgn(y - rhs.y);}// 两点相减 -> 得出向量pnt operator - (const pnt &rhs) const{return pnt(x - rhs.x, y - rhs.y);}// 向量点积double operator * (const pnt &rhs) const{return x * rhs.x + y * rhs.y;}// 向量叉积(的模)double operator ^ (const pnt &rhs) const{return x * rhs.y - rhs.x * y;}} vec; // vector// VECtor LENgth -> 向量长double veclen(const vec &v){return sqrt(v * v);}// Point to Segment -> 点 p 到线段 ab 距离double ps(const pnt &p, const pnt &a, const pnt &b){if(a == b)return veclen(p - a);vec ab = b - a, ap = p - a, bp = p - b;// 垂足在 a 点左边if(sgn(ab * ap) < 0)return veclen(ap);// 垂足在 b 点右边if(sgn(ab * bp) > 0)return veclen(bp);// 垂足在 ab 上return fabs(ab ^ ap) / veclen(ab);}
10、单位圆覆盖面积最大技巧
//思路:如果只有一个点,那么输出1 一个覆盖最多点的圆,必然至少有两个点在圆上。枚举两个点,求过这两个点的单位圆,判断有多少个点在圆中,枚举N^2,判断N
11、叉积
int Area(node a,node b){Return a.x*b.y-a.y*b.x;}//判断两线段的相对位置;//判断两线段有无交点://a,b为一条直线,cd同理,此处重载*int judge(line a, line b){if (((a.x2 - a.x1)*(b.y1 - a.y1) - (b.x1 - a.x1)*(a.y2 - a.y1))*((a.x2 - a.x1)*(b.y2 - a.y1) - (b.x2 - a.x1)*(a.y2 - a.y1)) > eps)return 0;if (((b.x2 - b.x1)*(a.y1 - b.y1) - (a.x1 - b.x1)*(b.y2 - b.y1))*((b.x2 - b.x1)*(a.y2 - b.y1) - (a.x2 - b.x1)*(b.y2 - b.y1)) > eps)return 0;return 1;}或者if(((b-a)*(c-a))*((b-a)*(d-a)) > 0 || ((d-c)*(a-c))*((d-c)*(b-c)) > 0)//两条线段根本没有交点{puts("0.00");continue;}//判断直线与线段有无交点://直线ab,线段cd://重载*为叉积If(((b-c)*(a-c))*((b-d)*(a-d)))<=0//有交点
12、已知两条线段四个端点,求交点
point Intersection(point a, point b, point c, point d){double t = ((d - a)*(c - a))/((b - a)*(d - c));//相似三角形return a + (b-a)*fabs(t);}
13、map
//用map存点用重载<缩点point base()const{if ( x == 0 && y < 0)return point(-x, -y);return *this;}bool operator<(const point&b)const{point p1 = base();point p2 = b.base();return p1.x*p2.y < p1.y*p2.x;}//Map中的点只有第一象限的,例如存a=(0,-1),b=(0,1)最终mp[a]=mp[b]=2;
14、字符串哈希
求字符串中一定长度的所有不同子串的数量:typedef long long ull;//自然哈希,自动取余const ull has= 233;//去一个较大的质数const int maxn = 1e6 + 10;char s[maxn];vector<ull>ve;int main(){int n,m;scanf("%d%d",&n,&m);scanf("%s",s);int len=strlen(s);ull r=1,sum=0;for(int i=0;i<n&&i<len;i++){sum=sum*has+s[i];//用数字保存第一个一点长度的字符串r*=has;}if(len>=n)ve.push_back(sum);for(int i=n;i<len;i++){sum=sum*has-s[i-n]*r+s[i];//去掉前一位加上后一位ve.push_back(sum);}sort(ve.begin(),ve.end());//必须排序int tot = unique(ve.begin(), ve.end()) - ve.begin();cout<<tot<<endl;return 0;}
15、统计一个字符串最长子序列,经过排序后可以构成回文串:(将字母转化为二进制数字求异或前缀和,若出现多次相同数字,则证明该点与前次出现的点能组成回文串。一个数异或另一个数两次得到原来的数)
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int N= 300005;const int INF=0x3f3f3f3f;const int mod=1000000007;typedef pair<int,int>P;char s[N];int n;map<int,int>mp;int main(){scanf("%d",&n);scanf("%s",s+1);int now=0,ans=0;mp[0]=0;for(int i=1;i<=n;i++){now^=(1<<(s[i]-'a'));//now与2的几次方异或if(mp.count(now)) ans=max(i-mp[now],ans);//异或得到原来的数,说明这一段数出现的次数都是偶数。else mp[now]=i;//记录这个值得下标for(int j=0;j<=20;j++){int y=1<<j;if(mp.count(now^y))ans=max(i-mp[now^y],ans);//出现aba这种情况,与b异或后可以得到now,}}printf("%\n",ans);return 0;}
