DESCRIPTION
今天HHHH 考完了期末考试,他在教学楼里闲逛,他看着教学楼里一间间的教室,于是开始思考:
如果从一个坐标为 (x1,y1,z1)(x1,y1,z1) 的教室走到(x2,y2,z2)(x2,y2,z2) 的距离为 |x1−x2|+|y1−y2|+|z1−z2||x1−x2|+|y1−y2|+|z1−z2|
那么有多少对教室之间的距离是不超过RR 的呢?
INPUT
第一行是一个整数T(1≤T≤10)T(1≤T≤10) , 表示有TT 组数据 接下来是TT 组数据,对于每组数据: 第一行是两个整数n,q(1≤n≤5×104,1≤q≤103)n,q(1≤n≤5×104,1≤q≤103) , 表示有nn 间教室, qq 次询问. 接下来是nn 行, 每行3个整数xi,yi,zi(0≤xi,yi,zi≤10)xi,yi,zi(0≤xi,yi,zi≤10) ,表示这间教室的坐标. 最后是qq 行,每行一个整数R(0≤R≤109)R(0≤R≤109) ,意思见描述.
OUTPUT
对于每个询问RR 输出一行一个整数,表示有多少对教室满足题目所述的距离关系.
SAMPLE INPUT
1 3 3 0 0 0 1 1 1 1 1 1 1 2 3
SAMPLE OUTPUT
1 1 3
HINT
对于样例,1号教室和2号教室之间的距离为3, 1号和3号之间的距离为3, 2号和3号之间的距离为0
SOLUTION
题解:考虑到坐标的范围非常小,我们可以统计每一个点有多少个教室,然后枚举坐标预处理答案,然后做一个前缀和即可
要小心的是R的范围 注意乘的时候会爆int
1 #pragma comment(linker, "/STACK:102400000,102400000") 2 #include <cstdio> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <algorithm> 7 #include <cmath> 8 #include <cctype> 9 #include <map> 10 #include <set> 11 #include <queue> 12 #include <bitset> 13 #include <string> 14 #include <complex> 15 #define ll long long 16 using namespace std; 17 int t; 18 int n,q; 19 int mp[15][15][15]; 20 int x[50004],y[50004],z[50004]; 21 int s[50004]; 22 ll sum[505]; 23 int main() 24 { 25 scanf("%d",&t); 26 for(int i=1;i<=t;i++) 27 { 28 for(int j=0;j<=10;j++) 29 for(int l=0;l<=10;l++) 30 for(int k=0;k<=10;k++) 31 mp[j][l][k]=0; 32 for(int j=0;j<=50;j++) 33 sum[j]=0; 34 scanf("%d %d",&n,&q); 35 int jishu=0; 36 for(int j=1;j<=n;j++) 37 { 38 scanf("%d %d %d",&x[j],&y[j],&z[j]); 39 if(mp[x[j]][y[j]][z[j]]==0) 40 s[jishu++]=j; 41 mp[x[j]][y[j]][z[j]]++; 42 } 43 for(int j=0;j<jishu;j++) 44 { 45 for(int k=j;k<jishu;k++) 46 { 47 if(j==k) 48 { 49 ll now=mp[x[s[j]]][y[s[j]]][z[s[j]]]; 50 sum[0]+=now*(now-1)/2; 51 } 52 else{ 53 int dis=abs(x[s[j]]-x[s[k]])+abs(y[s[j]]-y[s[k]])+abs(z[s[j]]-z[s[k]]); 54 sum[dis]+=mp[x[s[k]]][y[s[k]]][z[s[k]]]*mp[x[s[j]]][y[s[j]]][z[s[j]]]; 55 } 56 } 57 } 58 for(int j=1;j<=50;j++) 59 sum[j]+=sum[j-1]; 60 int exm; 61 for(int j=1;j<=q;j++) 62 { 63 scanf("%d",&exm); 64 if(exm>50) 65 printf("%lld ",sum[50]); 66 else 67 printf("%lld ",sum[exm]); 68 } 69 } 70 return 0; 71 }
DESCRIPTION
今天HHHH 在操场上跑步,HHHH 作为一个爱运动的人,肯定会想方设法把跑步所消耗的能量减到最少.
现在这个操场上有nn 个可以休息的点,他们的坐标分别为x1,x2...xn(xi≤xi+1)x1,x2...xn(xi≤xi+1) ,HHHH 刚开始在 x1x1 ,并且他只能在这些点休息,在中途不能停下来,否则会因为旁边的音浪太强而被晃到.
如果HHHH 连续跑一段长度为ll 的距离,那么他将会消耗2l+a2l+a 的能量(aa 为HHHH 的可爱值)
现在给你这些点的坐标,请帮HHHH 计算他跑到xnxn 点所需要消耗的能量最少是多少.
INPUT
第一行是一个整数T(1≤T≤10)T(1≤T≤10) ,表示有TT 组数据 对于每组数据输入一行2个整数n,a (1≤n≤105,1≤a≤106)n,a (1≤n≤105,1≤a≤106) 表示总共有nn 个休息点,HHHH 的可爱值为aa . 接着一行nn 个数x1,x2...,xn(0≤xi≤3×106,0≤xi+1−xi≤30)x1,x2...,xn(0≤xi≤3×106,0≤xi+1−xi≤30) ,表示点的位置.
OUTPUT
每组数据输出一行,一个整数,表示最小需要花费的体力
SAMPLE INPUT
2 3 2 3 5 7 3 10 3 5 7
SAMPLE OUTPUT
12 26
HINT
对于第一组样例,最少的体力消耗是先从3跑到5,消耗6点体力,再从5跑到7,消耗6点体力,共12点 对于第二组样例,最少的体力消耗是直接从3跑到7,消耗26点体力.
题解:
首先我们可以想到一个简单的dp方程
dp[i]=min(dp[j]+2^(dis[i]−dis[j]))+a
1.然后我们发现这个2^x很快就会比a 高到不知道哪里去,所以当这个距离超过一定值的时候肯定是分开
跑比较划算了,所以我们只需要枚举当前点前面的几十个点再转移一下就行了
2.我们也可以简单的推导一下发现这个dp方程是决策性单调的所以你懂的
1 #pragma comment(linker, "/STACK:102400000,102400000") 2 #include <cstdio> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <algorithm> 7 #include <cmath> 8 #include <cctype> 9 #include <map> 10 #include <set> 11 #include <queue> 12 #include <bitset> 13 #include <string> 14 #include <complex> 15 #define ll long long 16 using namespace std; 17 int t; 18 int aa[100005]; 19 int b[100005]; 20 ll dp[3000006]; 21 map<int,int>mp; 22 int n,a; 23 int main() 24 { 25 scanf("%d",&t); 26 int ans=0; 27 for(int j=1;j<=t;j++) 28 { 29 scanf("%d %d",&n,&a); 30 int jishu=0; 31 mp.clear(); 32 for(int i=1;i<=n;i++){ 33 scanf("%d",&aa[i]); 34 if(mp[aa[i]]==0){ 35 b[jishu++]=aa[i]; 36 mp[aa[i]]=1; 37 } 38 } 39 sort(b,b+jishu); 40 for(int i=0;i<jishu;i++){ 41 dp[i]=1e18+1; 42 } 43 dp[0]=0; 44 for(int i=1;i<jishu;i++) 45 { 46 for(int j=i-1;j>=0;j--) 47 { 48 if(b[i]-b[j]>30) 49 break; 50 dp[i]=min(dp[i],dp[j]+(1ll<<(b[i]-b[j]))+a); 51 } 52 } 53 printf("%lld ",dp[jishu-1]); 54 } 55 return 0; 56 }