4012: What is the Rank?
题意:给定n个数,按顺序将数添加进集合中,并输出该数在当前集合中是第几大
#include<bits/stdc++.h> using namespace std; const int Max=45005; struct node { int x,y; }e[Max]; int cmp(node a,node b) { return a.y>b.y; } int cmp1(node a,node b) { return a.x<b.x; } int f[Max]; void update(int x) { for(int i=x;i<Max;i+=i&-i) { f[i]+=1; } } int query(int x) { int sum=0; for(int i=x;i>0;i-=i&-i) { sum+=f[i]; } return sum; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&e[i].y); e[i].x=i; } sort(e+1,e+n+1,cmp); for(int i=1;i<=n;i++) { e[i].y=i; } sort(e+1,e+n+1,cmp1); for(int i=1;i<=n;i++) { update(e[i].y); printf("%d\n",query(e[i].y)); } }
//hash+树状数组
3656: Intersections
题意:给定一个圆和一条线段,求圆与线段是否相交
思路:1.线段两点均在圆内则不相交;
2.线段两点有一点在圆内,另一点在圆外则相交(有点在圆上为相交);
3.当两点均在圆外时,先求圆心在直线上的垂足,垂足在圆外则不相交,若垂足在圆内(包括圆上),继续判断线段两点是否相对垂足在同方向,同向为不相交,反向相交;
对点(x1,y1),(x2,y2)求出一般式:AX+BY+C=0
A=y2-y1 B=x1-x2 C=x2*y1-x1*y2
根据 A B C以及圆心(x,y)求出垂足(x3,y3)
x3=(b*b*x-a*b*y-a*c)/(a*a+b*b);y3=(a*a*y-a*b*x-b*c)/(a*a+b*b);
#include<bits/stdc++.h> using namespace std; void printY() { printf("The line segment intersects the circle.\n"); } void printN() { printf("The line segment does not intersect the circle.\n"); } int main() { double x,y,r,x1,y1,x2,y2; while(~scanf("%lf%lf%lf",&x,&y,&r)) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); double a=y2-y1; double b=x1-x2; double c=x2*y1-x1*y2; double x3=(b*b*x-a*b*y-a*c)/(a*a+b*b); double y3=(a*a*y-a*b*x-b*c)/(a*a+b*b); if((x-x1)*(x-x1)+(y-y1)*(y-y1)<r*r) { if((x-x2)*(x-x2)+(y-y2)*(y-y2)<r*r) printN(); else printY(); } else { if((x-x2)*(x-x2)+(y-y2)*(y-y2)<r*r) printY(); else { if((x-x3)*(x-x3)+(y-y3)*(y-y3)<=r*r) { if(x3==x2) { if((y3-y2)/abs(y3-y2)==(y3-y1)/abs(y3-y1)) printN(); else printY(); } else { if((x3-x2)/abs(x3-x2)==(x3-x1)/abs(x3-x1)) printN(); else printY(); } } else { printN(); } } } } }
//数学
4613: Number of Battlefields
题意:给定一个周长p,问有多少形状的周长为p(不能为矩形)
矩阵快速幂求斐波那契数列
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll MOD=987654321; void mul(ll b[2][2],ll a[2][2]) { ll c[2][2]={0}; for(int i=0;i<=1;i++) { for(int j=0;j<=1;j++) { c[i][j]=b[i][0]*a[0][j]%MOD+b[i][1]*a[1][j]%MOD; } } memcpy(b,c,sizeof(c)); } void power(ll a[2][2],int p) { ll b[2][2]={1,0,1,0}; while(p) { if(p&1) { mul(b,a); } mul(a,a); p/=2; } memcpy(a,b,sizeof(b)); } int main() { int p; while(scanf("%d",&p),p) { if (p&1||p<8) { printf("0\n"); continue; } p=(p-4)/2; ll a[2][2]={1,1,1,0}; power(a,2*p); printf("%lld\n",(a[1][0]-p-1+MOD)%MOD); } }
4505: KOSARE
题意:有n个盒子,m种类的玩具。n个盒子各自装有一定不同种类的玩具,现在请你选择一些盒子,使得这些盒子的玩具包含全部种类;问有多少种选择能够满足条件
#include<bits/stdc++.h> using namespace std; const int Max=(1<<20)+5; const int Mod=1000000007; int cnt[Max],num[Max],ans[Max]; int main() { int n,m; scanf("%d%d",&n,&m); cnt[0]=1; int f=1<<m; for(int i=1;i<=n;i++) { cnt[i]=(cnt[i-1]*2)%Mod; int k,s=0; scanf("%d",&k); for(int j=1;j<=k;j++) { int x; scanf("%d",&x); s+=1<<x-1; } num[s]++; } for(int i=0;i<m;i++) { for(int j=0;j<f;j++) { if(j&(1<<i))num[j]+=num[j-(1<<i)]; } } for(int i=0;i<f;i++) { ans[i]=cnt[num[i]]; } for(int i=0;i<m;i++) { for(int j=0;j<f;j++) { if(j&(1<<i))ans[j]=(ans[j]-ans[j-(1<<i)]+Mod)%Mod; } } printf("%d\n",ans[f-1]%Mod); }
//容斥原理+状压DP
6043: Tunnel Warfare
题意:一条直线上有n个村庄,目前有三种操作,D操作,将该村庄破坏,Q操作,查询有该村庄直接连接或间接连接的村庄数(包括自身),R操作将最近被破坏的村庄重建;
#include<bits/stdc++.h> using namespace std; const int Max=50005; struct node{ int llen,rlen,mlen; }e[Max*4]; void Build(int l,int r,int i) { e[i].llen=e[i].rlen=e[i].mlen=r-l+1; int mid=(l+r)/2; if(l==r)return ; Build(l,mid,i*2); Build(mid+1,r,i*2+1); } void Update(int l,int r,int i,int nod,int flag) { if(l==r) { e[i].llen=e[i].rlen=e[i].mlen=flag; return ; } int mid=(l+r)/2; if(nod<=mid)Update(l,mid,i*2,nod,flag); else Update(mid+1,r,i*2+1,nod,flag); e[i].llen=e[2*i].llen; e[i].rlen=e[2*i+1].rlen; e[i].mlen=max(max(e[i*2].mlen,e[i*2+1].mlen),e[i*2].rlen+e[i*2+1].llen); if(e[2*i].llen==mid-l+1) e[i].llen+=e[2*i+1].llen; if(e[i*2+1].rlen==r-mid) e[i].rlen+=e[2*i].rlen; } int Query(int l,int r,int i,int x) { if(l==r||e[i].mlen==0||e[i].mlen==r-l+1) { return e[i].mlen; } int mid=(l+r)/2; if(x<=mid) { if(x>=mid-e[i*2].rlen+1) return Query(l,mid,i*2,x)+Query(mid+1,r,i*2+1,mid+1); else return Query(l,mid,i*2,x); } else { if(x<=mid+1+e[i*2+1].llen-1) return Query(mid+1,r,i*2+1,x)+Query(l,mid,i*2,mid); else return Query(mid+1,r,i*2+1,x); } } stack<int> st; int main() { int n,m; scanf("%d%d",&n,&m); Build(1,n,1); for(int i=1;i<=m;i++) { getchar(); char ch; scanf("%c",&ch); if(ch=='D') { int x; scanf("%d",&x); Update(1,n,1,x,0); st.push(x); } else if(ch=='Q') { int x; scanf("%d",&x); printf("%d\n",Query(1,n,1,x)); } else { if(!st.size())continue; int x=st.top(); st.pop(); Update(1,n,1,x,1); } } }