A. Beru-taxi
水题
#include<bits/stdc++.h>
using namespace std;
int main()
{
double x,y;
while(cin>>x>>y){
int n;cin>>n;
double ans=99999999.0;
for(int i=0;i<n;i++){
double a,b,v;cin>>a>>b>>v;
ans=min(ans,sqrt((x-a)*(x-a)+(y-b)*(y-b))/v);
}
printf("%.10f\n",ans);
}
}
B. Interesting drink
题意:q(1<=q=100000)次询问某个数在n(1<=n<=100000)个数里比他小于等于的位置。
后话:那天晚上,我很困,看错题意看成求某个数在n个序列里,比他小而且连续的序列最长长度是。然后没想出来,睡着了….然后这场就跪了…
思路:排序(nlgn)后二分(q*lgn).
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++) scanf("%d",&a[i]);
int q;scanf("%d",&q);
sort(a,a+n);
while(q--){
int x;scanf("%d",&x);
int ans=upper_bound(a,a+n,x)-a;
printf("%d\n",ans);
}
}
}
C. Hard problem
题意:有n个字符串,对于每个串s[i]有一个翻转的功能,花费不等的c[i],问怎么样翻转使所有串按照字典序不递减的顺序。
思路:对每个串考虑就是翻不翻,只有两个状态,很水的动态规划,设dp[n][2],dp[i][0]表示从第一个串当前第i个串不翻转的耗费,dp[i][1]表示从第一个串到当前i串翻转的耗费。
转移方程从当前串与上一个串字典序大小关系进行转移。
#include<bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
typedef long long ll;
ll dp[maxn][2],c[maxn];
string s[maxn],rs[maxn];
const ll inf=0x7fffffffffff;
int main(){
int n;
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++) scanf("%I64d",&c[i]);
for(int i=0;i<=n;i++){
dp[i][0]=inf;
dp[i][1]=inf;
}
dp[0][0]=0;dp[0][1]=0;
for(int i=1;i<=n;i++){
cin>>s[i];rs[i]=s[i];
reverse(rs[i].begin(),rs[i].end());
if(s[i]>=s[i-1]) dp[i][0]=min(dp[i][0],dp[i-1][0]);
if(s[i]>=rs[i-1]) dp[i][0]=min(dp[i][0],dp[i-1][1]);
if(rs[i]>=s[i-1]) dp[i][1]=min(dp[i][1],dp[i-1][0]+c[i]);
if(rs[i]>=rs[i-1]) dp[i][1]=min(dp[i][1],dp[i-1][1]+c[i]);
}
ll ans=min(dp[n][0],dp[n][1]);
if(ans==inf) printf("-1\n");
else printf("%I64d\n",ans);
}
}
D. Vasiliy’s Multiset
题意:进行n次操作 首先0 在集合内
+ 表示将 x加入集合内
- 表示将x从集合里删除
? 表示查询x与集合内的数的 异或的最大值
思路:异或最大值,实际上就在集合里找与x二进制位1出现位置不同最多的那个数。
我们可以把每个数二进制化放在一棵树里,然后查找位置1不同最多的那个数。这题就是类是一个字典树的写法。每层就是0,1.思路很清晰。
#include<bits/stdc++.h>
using namespace std;
struct node{
int one,zero,cnt1,cnt0;
}a[10000000+10];
int t;
int main(){
int n;
while(~scanf("%d",&n)){
memset(a,0,sizeof(a));
t=1;
for(int i=0;i<=n;i++){
char c;int x;
if(i==0) { c='+';x=0;}
else scanf(" %c %d",&c,&x);
if(c=='+'){
int bit[32],v=1;
for(int i=0;i<32;i++){
bit[i]=x%2;x/=2;
}
for(int i=31;i>=0;i--){
if(bit[i]==1){
a[v].cnt1++;
if(a[v].one==0) a[v].one=++t;
v=a[v].one;
}
else{
a[v].cnt0++;
if(a[v].zero==0) a[v].zero=++t;
v=a[v].zero;
}
}
}
else if(c=='-'){
int bit[32],v=1;
for(int i=0;i<32;i++){
bit[i]=x%2;x/=2;
}
for(int i=31;i>=0;i--){
if(bit[i]==1){
a[v].cnt1--;
v=a[v].one;
}
else{
a[v].cnt0--;
v=a[v].zero;
}
}
}
else if(c=='?'){
int ans=0;
int bit[32],v=1;
for(int i=0;i<32;i++){
bit[i]=x%2;x/=2;
}
for(int i=31;i>=0;i--){
if(bit[i]==1){
if(a[v].cnt0>0){
ans+=(1<<i);
v=a[v].zero;
}
else v=a[v].one;
}
else{
if(a[v].cnt1>0){
ans+=(1<<i);
v=a[v].one;
}
else v=a[v].zero;
}
}
printf("%d\n",ans);
}
}
}
}
E. Working routine
题意:在一个矩阵(1000*1000)里q(1<=q<=10000)次交换两个不相交小矩阵,怎么模拟时间复杂度最低?
思路:思考交换两个矩阵相对于每个点来说,只有矩阵的边周围的点关系变换了,中间的点四周的点并没有变化呢。所以最简单的做法就是存每个点四周点事什么,实际只用存右边,下边点是什么。然后转换的过程只用转换小矩阵四条边。O(q*(n+m))时间复杂度
#include<bits/stdc++.h>
using namespace std;
const int maxn=1050;
struct node{
int v;
node *right,*down;
}s[maxn][maxn];
int main(){
int n,m,q;
while(~scanf("%d %d %d",&n,&m,&q)){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&s[i][j].v);
}
}
for(int i=0;i<=n;i++){
for(int j=0;j<=m;j++){
s[i][j].right=&s[i][j+1];
s[i][j].down=&s[i+1][j];
}
}
while(q--){
int a,b,c,d,h,w;
scanf("%d %d %d %d %d %d",&a,&b,&c,&d,&h,&w);
node *nowu[2]={&s[a-1][0],&s[c-1][0]};
node *nowd[2]={&s[a-1+h][0],&s[c-1+h][0]};
for(int i=1;i<=b;i++){
nowu[0]=nowu[0]->right;
nowd[0]=nowd[0]->right;
}
for(int i=1;i<=d;i++){
nowu[1]=nowu[1]->right;
nowd[1]=nowd[1]->right;
}
node *nowl[2]={&s[0][b-1],&s[0][d-1]};
node *nowr[2]={&s[0][b-1+w],&s[0][d-1+w]};
for(int i=1;i<=a;i++){
nowl[0]=nowl[0]->down;
nowr[0]=nowr[0]->down;
}
for(int i=1;i<=c;i++){
nowl[1]=nowl[1]->down;
nowr[1]=nowr[1]->down;
}
for(int i=1;i<=h;i++){
swap(nowl[0]->right,nowl[1]->right);
nowl[0]=nowl[0]->down;nowl[1]=nowl[1]->down;
swap(nowr[0]->right,nowr[1]->right);
nowr[0]=nowr[0]->down;nowr[1]=nowr[1]->down;
}
for(int i=1;i<=w;i++){
swap(nowu[0]->down,nowu[1]->down);
nowu[0]=nowu[0]->right;nowu[1]=nowu[1]->right;
swap(nowd[0]->down,nowd[1]->down);
nowd[0]=nowd[0]->right;nowd[1]=nowd[1]->right;
}
}
for(int i=1;i<=n;i++){
node *now=&s[i][0];
for(int j=1;j<=m;j++){
now=now->right;
printf("%d ",now->v);
}
printf("\n");
}
}
}