赞
踩
贪心,每一位取t和9-t中较小的。注意首位不能为0。
- #include <iostream>
- #include <stdio.h>
- #include <string>
- #include <map>
- #include <vector>
- #include <stack>
- #include <queue>
- #include <string.h>
- #include <algorithm>
- #include <math.h>
-
- using namespace std;
-
- char num[22];
-
- int main(){
- scanf("%s",num);
- int len=strlen(num);
- for(int i=0;i<len;i++){
- int t=num[i]-'0';
- t=min(t,9-t);
- if(i==0&&t==0)t=9;
- printf("%d",t);
- }
- return 0;
- }

首先,把x0,y0平移到原点。然后所有的x和y也跟着平移。判断的时候,暴力扫一遍,如果两个点的交叉乘积相等,它们的连线肯定过原点。
- #include <iostream>
- #include <stdio.h>
- #include <string>
- #include <map>
- #include <vector>
- #include <stack>
- #include <queue>
- #include <string.h>
- #include <algorithm>
- #include <math.h>
-
- using namespace std;
-
- int x[1010];
- int y[1010];
- bool flag[1010];
-
- int main(){
- int n;
- cin>>n>>x[0]>>y[0];
- for(int i=1;i<=n;i++){
- cin>>x[i]>>y[i];
- x[i]-=x[0];
- y[i]-=y[0];
- }
-
- int ans=0;
- for(int i=1;i<=n;i++){
- if(flag[i])continue;
- ans++;
- flag[i]=1;
- for(int j=i+1;j<=n;j++){
- if(x[i]*y[j]==x[j]*y[i])flag[j]=1;
- }
- }
- cout<<ans<<endl;
- return 0;
- }

在字典树上dfs。因为整个串只会出现abc三种字符,所以在每个节点,尝试沿着三条不同的路径往下走,注意和原串不同的路径只能走一次且必须走一次。详见代码注释。
- #include <iostream>
- #include <stdio.h>
- #include <string>
- #include <map>
- #include <vector>
- #include <stack>
- #include <queue>
- #include <string.h>
- #include <algorithm>
- #include <math.h>
-
- using namespace std;
-
- struct node{
- int next[3];
- bool flag; //flag=1表示是串结尾
- }Trie[600010];
-
- char tmp[600010];
-
- //k为串的位置,index为字典树中节点位置
- bool dfs(int k,int index,bool diff){
- if(k!=0&&index==0)return 0; //找不到
- if(tmp[k]=='\0'){ //串的结尾
- if(Trie[index].flag&&diff) return 1; //字典树中也遇到结尾,且恰有一个字符不同
- else return 0;
- }
-
- bool f=Trie[index].flag;
- for(int i=0;i<3;i++){
- if(i+'a'==tmp[k]){ //与串的字符相同
- if(dfs(k+1,Trie[index].next[i],diff))return 1;
- }else{
- if(!diff){ //与串的字符不同,若之前没出现过不同,则可以继续搜索
- if(dfs(k+1,Trie[index].next[i],1))return 1;
- }
- }
- }
- return 0;
- }
-
- int main(){
- int n,m;
- cin>>n>>m;
- int pos=0;
- for(int i=1;i<=n;i++){
- scanf("%s",tmp);
- int len=strlen(tmp);
- int cur=0;
- for(int j=0;j<len;j++){
- int next=Trie[cur].next[tmp[j]-'a'];
- if(next==0){
- next=++pos;
- Trie[cur].next[tmp[j]-'a']=next;
-
- }
- if(j==len-1){
- Trie[next].flag=1;
- }
- cur=next;
- }
- }
-
- for(int i=1;i<=m;i++){
- scanf("%s",tmp);
- if(dfs(0,0,0)){
- printf("YES\n");
- }else{
- printf("NO\n");
- }
- }
- return 0;
- }

注意到m非常小,我们可以用two pointers+spare table来解决。我们对每个特性都开一个spare table,就可以迅速查询该特性区间内的最大值。然后用two pointers扫一遍解决。
- #include <iostream>
- #include <stdio.h>
- #include <string>
- #include <map>
- #include <vector>
- #include <stack>
- #include <queue>
- #include <string.h>
- #include <algorithm>
- #include <math.h>
-
- using namespace std;
-
- const int maxn=100010;
-
- int a[5][maxn][18];
- int pow2n[18];
-
- int ans[5];
- int tmp[5];
-
- int query_max(int mec,int l,int r){
- int d=r-l+1;
- int k=-1;
- while(d){
- k++;
- d>>=1;
- }
- return max(a[mec][l][k],a[mec][r-(1<<k)+1][k]);
- }
-
- int main(){
- pow2n[0]=1;
- for(int i=1;i<18;i++)pow2n[i]=pow2n[i-1]<<1;
-
- int n,m,k;
- cin>>n>>m>>k;
- for(int i=1;i<=n;i++){
- for(int j=0;j<m;j++){
- scanf("%d",&a[j][i][0]);
- }
- }
- for(int i=0;i<m;i++){
- for(int j=1;pow2n[j]<=n;j++){
- for(int k=1;k+pow2n[j-1]<=n;k++){
- a[i][k][j]=max(a[i][k][j-1],a[i][k+pow2n[j-1]][j-1]);
- }
- }
- }
-
- int L=1;
- int R=1;
- int MAX=0;
-
- while(R<=n){
- int sum=0;
- for(int i=0;i<m;i++){
- tmp[i]=query_max(i,L,R);
- sum+=tmp[i];
- }
- if(sum>k){
- L++;
- if(R<L)R++;
- }else{
- if(R-L+1>MAX){
- MAX=R-L+1;
- memcpy(ans,tmp,sizeof(ans));
- }
- R++;
- }
- }
-
- for(int i=0;i<m;i++){
- printf("%d ",ans[i]);
- }
-
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。