您的位置:首页 > 大数据 > 人工智能

2016 Multi-University Training Contest 10

2016-12-07 22:34 246 查看
开始刷多校,今天第一弹。

话说,多校的题目真的好难。。。

Median HDU 5857

给定一个有序序列,然后给定两个区间[l1,r1],[l2,r2]产生新的序列。

要求新序列的中位数。

分三种情况考虑。

1.区间没交集。

2.区间半交。

3.区间全包裹。

各自找到自己的位置就好。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

int a[100005];
int T,n,m,l1,l2,r1,r2;

double find(int a[],int x){
if(r1<=l2){
if(x<=r1-l1+1) return a[l1+x-1];
else return a[l2+x-1-r1+l1-1];
}
else if(r1<=r2){
if(x<=l2-l1) return a[l1+x-1];
else if(x>r1-l1+1+r1-l2+1) return a[l2+x-r1+l1-1-1];
else return a[l2+(x-l2+l1+1)/2-1];
}
else{
swap(r1,r2);  // l1,r2,r1,l2
if(x<=l2-l1) return a[l1+x-1];
else if(x>r1-l1+1+r1-l2+1) return a[l2+x-r1+l1-1-1];
else return a[l2+(x-l2+l1+1)/2-1];
}
}

int main(){
cin>>T;
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",a+i);

for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);

d42a
int len = r1-l1+1 + r2-l2+1;
if(l1>l2){
int t =l1;l1=l2;l2=t;
t =r1;r1=r2;r2=t;
}
double mid;
if(len&1) mid = find(a,len/2+1);
else mid = 0.5*find(a,len/2) + 0.5*find(a,len/2+1);
printf("%.1lf\n",mid);
}
}

return 0;
}


Hard problem

解析几何吧。先建系算出交点的坐标,然后就能算出来了。

#include <cstdio>
#include <cmath>
#include <iostream>

using namespace std;

double calc(int l){
double t1 = asin(sqrt(14.0)/8.0);
double t2 = asin(sqrt(14.0)/4.0);
double s2 = l * l * 1.0 / 8 * t2 * 2;
double s1 = l * l * 1.0 / 2 * t1 * 2 - sqrt(7) / 8 * l * l;
return (s2 - s1)*2.0;
}

int main(){
int T,l;
cin>>T;
while(T--){
cin>>l;
printf("%.2lf\n",calc(l));
}
return 0;
}


Death Sequence

动规题。

先算i在第几轮死掉。有方程f[i]=i%k?f[i-i/k-1]+1:0;

然后累计前面死的人的个数就好了。

前几轮死的人说 a[i]=i%k?a[i-i/k-1]:i/k+1;

加上预处理的left[f[i]]即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;
const int MAXN = 3000010;
int ans[MAXN],f[MAXN],a[MAXN],LEFT[MAXN];
int T,n,k,q,x;

void solve(){
int t = n;
int tot = 0;
LEFT[0] = 0;
while(t){
tot++;
LEFT[tot] = LEFT[tot-1]+(t-1)/k+1;
t-=(t-1)/k+1;
}
memset(f,0,sizeof(f));
memset(a,0,sizeof(a));
for(int i=0;i<n;i++){
f[i]=(i%k)?f[i-i/k-1]+1:0;
a[i]=(i%k)?a[i-i/k-1]:i/k+1;
}

for(int i=0;i<n;i++){
int t=LEFT[f[i]]+a[i];
ans[t]=i;
}
}

int main(){
cin>>T;
while(T--){
memset(ans,0,sizeof(ans));
scanf("%d%d%d",&n,&k,&q);
solve();
for(int i=1;i<=q;i++){
scanf("%d",&x);
printf("%d\n",ans[x]+1);
}
}
return 0;
}


Counting Intersections

给定一系列平行于坐标轴的直线,求其交点的个数。

参考线段树扫描线做法。

对于横着的线段,左端点+1,右端点-1。这样累计的时候可以巧妙的去掉没有交点的线。对于竖着的线段,就查询。

处理的时候需要离散化。

以及ans要用long long

#include <cstdio>
#include <cstring>
#include <iostream>
#include <climits>
#include <algorithm>
#include <map>
#define LL long long

using namespace std;

const int MAXN = 100005;

struct node{
int tp,x,y,y2;
}info[MAXN*2];
int a[MAXN*2],sum[MAXN*2],Maxn;
map<int,int> mp;

bool cmp(node a,node b){
return (a.x<b.x)||(a.x==b.x&&a.tp<b.tp);
}

void insert(int BIT,int tp,int x,int y,int y2){
info[BIT].tp=tp;
info[BIT].x = x;
info[BIT].y = y;
info[BIT].y2=y2;
}

int lowbit(int k){return k&(-k);}

void add(int k,int delta){
while(k<=Maxn){
sum[k]+=delta;
k+=lowbit(k);
}
}

int query(int k){
int s = 0;
while(k){
s+=sum[k];
k-=lowbit(k);
}
return s;
}

int main(){
int T,n;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
int tot=0,all=0;
for(int i=1;i<=n;i++){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
if(x1==x2){//竖 1
if(y1>y2) swap(y1,y2);
insert(++tot,1,x1,y1,y2);
a[++all]=y1;
a[++all]=y2;
} else {//横 0
if(x1>x2) swap(x1,x2);
insert(++tot,0,x1,y1,1);
insert(++tot,0,x2+1,y2,-1);
a[++all]=y1;
}
}
sort(a+1,a+1+all);
int cnt = 0;
mp.clear();
for(int i=1;i<=all;i++)
if(!mp[a[i]]) mp[a[i]]=++cnt;
Maxn = cnt + 1;
memset(sum,0,sizeof(sum));
sort(info+1,info+1+tot,cmp);
LL ans = 0;

for(int i=1;i<=tot;i++){
if(info[i].tp==0){
int tp = mp[info[i].y];
add(tp,info[i].y2);
} else {
int l = mp[info[i].y],r=mp[info[i].y2];
ans += query(r) - query(l-1);
}
}
printf("%I64d\n",ans);
}
return 0;
}


Water problem

求 1~n 这n个数字的英文写法的总长度. (不算空格和连字符)

模拟题。

特殊处理1-19。20-1000的话直接算个位十位+百位就行了。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int bit1[] = {4,3,3,5,4,4,3,5,5,4,3,6,6,8,8,7,7,9,8,8};
int bit2[] = {0,0,6,6,5,5,5,7,6,6};
int hundred, thousand;
int cnt[1100];
void solve(){
hundred = 7; thousand = 8;
cnt[1000] = 11;
for(int i=1; i<1000; i++) {
if(i < 20) cnt[i] = bit1[i];
else if(i < 100){
int m = i;
cnt[i] = bit2[m/10];
if(m%10) cnt[i] += bit1[m%10];
}
else {
int m = i;
cnt[i] = bit1[m/100] + hundred;
if(!(m%100)) continue;
cnt[i] += cnt[m%100] + 3;
}
}
for(int i=1; i<=1000; i++) cnt[i] += cnt[i-1];
}
int main(){
solve();
int T;
cin>>T;
while(T--){
int n;
scanf("%d",&n);
printf("%d\n",cnt
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: