@meredith233
2017-04-14T16:07:52.000000Z
字数 4867
阅读 885
homework
给定一个二进制数,给定两种操作。操作‘I’对给定区间[a,b]内的数进行取反操作。操作‘Q’查询第i个位置的数是0还是1.
用线段树的区间更新来记录每个位置取反的次数,而后查询时如果取反次数为奇数次则对该数取反。后输出。
#include <cstdio>#include <iostream>#include <algorithm>#include <cmath>#include <cstring>#define PI acos(-1.0)#define MAX 100005using namespace std;int tre[MAX*4],laz[MAX*4];char ar[MAX];void pushdown(int num){if(laz[num]!=0){tre[num*2]+=laz[num];tre[num*2+1]+=laz[num];laz[num*2]+=laz[num];laz[num*2+1]+=laz[num];laz[num]=0;}}void update(int num,int l,int r,int x,int y){if(x<=l&&y>=r){tre[num]++;laz[num]++;return;}pushdown(num);int mid=(l+r)/2;if(x<=mid)update(num*2,l,mid,x,y);if(y>mid)update(num*2+1,mid+1,r,x,y);}int query(int num,int l,int r,int x){if(l==r)return tre[num];pushdown(num);int mid=(l+r)/2;if(x<=mid)return query(num*2,l,mid,x);elsereturn query(num*2+1,mid+1,r,x);}int main(){//freopen("test.txt","r",stdin);int t,cnt=0;scanf("%d",&t);while(t--){memset(tre,0,sizeof(tre));memset(laz,0,sizeof(laz));scanf("%s",ar+1);int n=strlen(ar+1);int q;printf("Case %d:\n",++cnt);scanf("%d",&q);while(q--){char c;int a,b;scanf(" %c",&c);if(c=='I'){scanf("%d%d",&a,&b);update(1,1,n,a,b);}if(c=='Q'){scanf("%d",&a);int x=query(1,1,n,a);int ans=ar[a]-'0';if(x%2==1)ans=!ans;printf("%d\n",ans);}}}return 0;}
输入一串数字,然后输入a,b,查询大于等于a且小于等于b的数字有多少个。
二分查找,先对输入的数字串进行排序,后进行两次二分分别查询范围内最小值和最大值所在位置,输出即可。
#include <cstdio>#include <iostream>#include <algorithm>using namespace std;int ar[100005];int main(){//freopen("test.txt","r",stdin);int t,cnt=0;scanf("%d",&t);while(t--){int n,q;scanf("%d%d",&n,&q);for(int i=0;i<n;i++)scanf("%d",&ar[i]);sort(ar,ar+n);printf("Case %d:\n",++cnt);while(q--){int a,b;scanf("%d%d",&a,&b);int l=0,r=n-1;while(l<=r){int mid=(l+r)>>1;if(ar[mid]<a)l=mid+1;elser=mid-1;}//cout<<l<<" "<<r<<endl;a=l;l=0,r=n-1;while(l<=r){int mid=(l+r)>>1;if(ar[mid]<=b)l=mid+1;elser=mid-1;}//cout<<l<<" "<<r<<endl;b=l;printf("%d\n",b-a);}}return 0;}
给定一个大圆半径R,以及大圆内的小圆个数n,求小圆的半径r。
连接大圆圆心与相邻两个小圆圆心,可得其角度为2PI/n,而后连接大圆圆心与两小圆心中点,可得公式r=R*sin(PI/n)/(1+sin(PI/n))。在该题中,需要注意在r为整数时输出整数,否则保留10位小数。
#include <cstdio>#include <iostream>#include <algorithm>#include <cmath>#define PI acos(-1.0)using namespace std;int main(){int t,cnt=0;scanf("%d",&t);while(t--){double R,r;int n;scanf("%lf%d",&R,&n);r=R*sin(PI/(double)n)/(1.0+sin(PI/(double)n));//jint x=(int)r;double xx=(double)x;if(r-xx<1e-12)printf("Case %d: %.0lf\n",++cnt,r);elseprintf("Case %d: %.10lf\n",++cnt,r);}return 0;}
有n户人,要涂上红,绿,蓝三种颜色,且相邻两户颜色不能相同,给定每户涂每种颜色所需花费,求最小花费。
动态规划,每次求与上一户人家不同颜色时花费最小。
#include <cstdio>#include <iostream>#include <algorithm>#include <cmath>#include <cstring>#define PI acos(-1.0)#define MAX 100005#define INF (1<<20)using namespace std;int ar[25][5],dp[25][5];int main(){int t,cnt=0;scanf("%d",&t);while(t--){memset(dp,0,sizeof(dp));int n;scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d%d%d",&ar[i][0],&ar[i][1],&ar[i][2]);for(int i=0;i<3;i++)dp[0][i]=ar[0][i];for(int i=1;i<n;i++){for(int j=0;j<3;j++){if(j==0)dp[i][j]=ar[i][j]+min(dp[i-1][1],dp[i-1][2]);if(j==1)dp[i][j]=ar[i][j]+min(dp[i-1][0],dp[i-1][2]);if(j==2)dp[i][j]=ar[i][j]+min(dp[i-1][0],dp[i-1][1]);}}int ans=INF;for(int i=0;i<3;i++)ans=min(ans,dp[n-1][i]);printf("Case %d: %d\n",++cnt,ans);}return 0;}
给定n个数q个查询,求区间最小值。
线段树裸题,求区间最小值。
#include <cstdio>#include <iostream>#include <algorithm>#define MAX 100000#define INF (1<<20)using namespace std;int tre[MAX*4];void build(int num,int l,int r){if(l==r){scanf("%d",&tre[num]);return;}int mid=(l+r)>>1;build(num*2,l,mid);build(num*2+1,mid+1,r);tre[num]=min(tre[num*2],tre[num*2+1]);}int query(int num,int l,int r,int x,int y){if(x<=l&&y>=r)return tre[num];int mid=(l+r)>>1;int ans=INF;if(x<=mid)ans=min(ans,query(num*2,l,mid,x,y));if(y>mid)ans=min(ans,query(num*2+1,mid+1,r,x,y));return ans;}int main(){int t,cnt=0;scanf("%d",&t);while(t--){int n,q;scanf("%d%d",&n,&q);build(1,1,n);printf("Case %d:\n",++cnt);while(q--){int a,b;scanf("%d%d",&a,&b);printf("%d\n",query(1,1,n,a,b));}}return 0;}
给定一棵树,需要找出树上任意两点间的最长距离。
树的直径问题,先对任一点dfs求出直径的一个端点,后对这个端点求dfs,可得答案。
#include<cstdio>#include<queue>#include<cstring>#include<algorithm>#define MAX 30005#define INF (1<<20)using namespace std;int n,m,len,dis[MAX],head[MAX],ans,T;bool vis[MAX];struct edge{int to,val,next;}e[MAX*2];void add(int from,int to,int val){e[len].to=to;e[len].val=val;e[len].next=head[from];head[from]=len++;}void bfs(int s){memset(vis,0,sizeof(vis));memset(dis,INF,sizeof(dis));queue<int>q;q.push(s);dis[s]=0;vis[s]=true;ans=0;while(!q.empty()){int cur=q.front();q.pop();for(int i=head[cur];i!=-1;i=e[i].next){int id=e[i].to;if(!vis[id]){vis[id]=true;dis[id]=dis[cur]+e[i].val;if(ans<dis[id]){ans=dis[id];T=id;}q.push(id);}}}}int main(){int t,cnt=0;scanf("%d",&t);while(t--){memset(head,-1,sizeof(head));len=0;int n;scanf("%d",&n);for(int i=0;i<n-1;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);add(a,b,c);add(b,a,c);}bfs(0);bfs(T);printf("Case %d: %d\n",++cnt,ans);}return 0;}