10-20
阿新 • • 發佈:2017-10-20
std ems 一個人 ace bfs tor start else tchar
比較水的題目吧
T1:給一個序列,序列中有四種操作,問有多少個非空子序列令一個機器人經過變換後再回到原位
數據量很小,n^2拿80,另外20只有左右兩種命令,求一個類似於前綴和的東西,如果sumi==sumj證明有一種
#include<bits/stdc++.h> using namespace std; struct hehe{ int x,y; }; int n,cnt[800100]; char s[400100]; void work1(){ hehe a; int ans=0; for(int i=1;i<=n;++i){ a.x=0; a.y=0; for(int j=i;j<=n;++j){ if(s[j-1]==‘U‘) a.y++; else if(s[j-1]==‘D‘) a.y--; else if(s[j-1]==‘L‘) a.x--; else if(s[j-1]==‘R‘) a.x++; if(!a.x && !a.y) ans++; } } cout<<ans<<endl; } void work2(){int x=0,ans=0; for(int i=1;i<=n;++i){ int xx=x; if(xx<0) xx=n-xx; ans+=cnt[xx]; cnt[xx]++; if(s[i-1]==‘L‘) x++; else if(s[i-1]==‘R‘) x--; } cout<<ans<<endl; } int main(){ freopen("command.in","r",stdin); freopen("command.out","w",stdout); cin>>n; scanf("%s",s); if(n<=4000) work1(); else work2(); fclose(stdin);fclose(stdout); return 0; }
T2:將n種顏色塗到n種卡片上,每種卡片有兩張,將兩張卡片一個正面朝上,一個反面朝上,打亂後將一個正面朝上的和一個反面朝上的放到一張桌子上(總共n張桌子),一個人會用1s的時間打開一個桌子上的反過來的卡片,並且走到另一個正面是這個顏色的桌子,對於Q次詢問,求每次ki秒後這個人在哪站著。
對於30%的數據來說模擬即可,對於100%的數據來說,考慮到一定會出現循環的情況,做一個類似於連通分量的東西,求出每一個塊的循環節y,那麽問題就是每次詢問的ki%y後的數怎麽處理了。我的做法是開了一個結構體,存了每個桌子屬於第幾個塊,在這個塊中他是第幾個,這樣排序後就能O(1)的時間解決ki%y後的問題了
#include<bits/stdc++.h> using namespace std; struct hehe{ int x,y,dfn; }a[100100]; struct hh{ int op,id,s,dfn; }a1[100100]; struct haha{ int id,y; }e[100100]; int n,m,cnt=0,op[100100],kuai[100100],num=0,start[100100]; inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘) f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch-‘0‘); ch=getchar();} return x*f; } inline void put(int x){ char ch[30]; int t=0; if(x<0){ putchar(‘-‘); x=-x; } else if(x==0) putchar(‘0‘); while(x){ ch[++t]=x%10+‘0‘; x/=10; } while(t) putchar(ch[t--]); putchar(‘\n‘); } void work1(){ int x,y; int cnt=0; for(int i=1;i<=m;++i){ x=read(); y=read(); for(cnt=1;cnt<=y;++cnt){ x=e[a[x].y].id; } put(x); } } int dfs(int x){ num++; op[x]=cnt; a[x].dfn=num; a1[x].dfn=num; a1[x].op=cnt; int Next=e[a[x].y].id; if(!op[Next]) dfs(Next); } bool mycmp(hh x,hh y){ return (x.op<y.op ||x.op==y.op && x.dfn<y.dfn); } void work2(){ for(int i=1;i<=n;++i){ if(!op[i]){ num=0; cnt++; int x=i; while(!op[x]){ op[x]=cnt; num++; a[x].dfn=num; a1[x].dfn=num; a1[x].op=cnt; x=e[a[x].y].id; } kuai[cnt]=num; } } sort(a1+1,a1+n+1,mycmp); for(int i=1;i<=n;++i){ if(a1[i].op==a1[i-1].op) a1[i].s=a1[i].s; else{ a1[i].s=i; start[a1[i].op]=i; } } int x,y; for(int i=1;i<=m;++i){ x=read(); y=read(); y+=a[x].dfn-1; int z=op[x]; y%=kuai[z]; int s=start[op[x]]+y; put(a1[s].id); } } int main(){ freopen("position.in","r",stdin); freopen("position.out","w",stdout); n=read(); m=read(); int x,y; for(int i=1;i<=n;++i){ x=read(); y=read(); e[x].y=y; e[x].id=i; a[i].x=x; a[i].y=y; a1[i].id=i; } if(n<=20) work1(); else work2(); fclose(stdin);fclose(stdout); return 0; }
T3:給一個圖,邊權為1,現要求從s1到t1不超過l1,從s2到t2不超過l2,求最多能刪除多少邊
求出每兩個點之間的距離,然後枚舉s1->t1,s2->t2的重疊的邊,在剩下的圖中盡量選用這些重疊的邊,這樣就能保證圖中刪掉的邊是最多的
#include <iostream> #include <vector> #include <cstring> #include <queue> using namespace std; const int MAXN=3010; struct hehe{ int y,next; }e[10000]; int n, m,s1, t1, l1,s2, t2, l2,dis[MAXN][MAXN],lin[MAXN],len=0; bool vis[MAXN]; inline void insert(int x,int y){ e[++len].next=lin[x]; lin[x]=len; e[len].y=y; } inline int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘) f=-1; ch=getchar();} while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch-‘0‘); ch=getchar();} return x*f; } void bfs(){ for(int i=1;i<=n;i++){ memset(vis,0,sizeof(vis)); queue<int>q; q.push(i); vis[i]=1; while(!q.empty()){ int x=q.front(); q.pop(); for(int j=lin[x];j;j=e[j].next){ int y=e[j].y; if(!vis[y]){ vis[y]=1; dis[i][y]=dis[i][x]+1; q.push(y); } } } } } bool check(int s1, int t1, int s2, int t2, int i, int j){ return dis[s1][i]+dis[i][j]+dis[j][t1]<=l1 && dis[s2][i]+dis[i][j]+dis[j][t2]<=l2; } int main(){ freopen("destroy.in","r",stdin); freopen("destroy.out","w",stdout); n=read(); m=read(); int x,y; for (int i = 1; i <= m; i++){ x=read(); y=read(); insert(x,y); insert(y,x); } s1=read(); t1=read(); l1=read(); s2=read(); t2=read(); l2=read(); bfs(); int ans=dis[s1][t1]+dis[s2][t2]; if(dis[s1][t1]>l1 || dis[s2][t2]>l2){ cout<<"-1"<<endl; } else{ for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ if(check(s1,t1,s2,t2,i,j)){ ans = min(ans,dis[s1][i]+dis[i][j]+dis[j][t1]+dis[s2][i]+dis[j][t2]); } if(check(t1,s1,t2,s2,i,j)){ ans = min(ans,dis[t1][i]+dis[i][j]+dis[j][s1]+dis[t2][i]+dis[j][s2]); } if(check(s1,t1,t2,s2,i,j)){ ans = min(ans,dis[s1][i]+dis[i][j]+dis[j][t1]+dis[t2][i]+dis[j][s2]); } if(check(t1,s1,s2,t2,i,j)){ ans = min(ans,dis[t1][i]+dis[i][j]+dis[j][s1]+dis[s2][i]+dis[j][t2]); } } } cout<<m-ans<<endl; } return 0; }
T4emmmm
題目看不懂,題解看不懂,標程看不懂........
10-20