Noip 2017 题目整理
2017Noip:
小凯的疑惑
题目描述
小凯手中有两种面值的金币,两种面值均为正整数且彼此互素。每种金币小凯都有无数个。在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的。现在小凯想知道在无法准确支付的物品中,最贵的价值是多少金币?注意:输入数据保证存在小凯无法准确支付的商品。
输入格式
输入数据仅一行,包含两个正整数 a和b,它们之间用一个空格隔开,表示小凯手中金币的面值。
输出格式
输出文件仅一行,一个正整数N,表示不找零的情况下,小凯用手中的金币不能准确支付的最贵的物品的价值。
样例输入
3 7
样例输出
11
样例说明
小凯手中有面值为3和7的金币无数个,在不找零的前提下无法准确支付价值为 1、2、4、5、8、11的物品,其中最贵的物品价值为11。比11贵的物品都能买到,比如:
12=3×4+7×0 12 = 3
13=3×2+7×113 = 3
14=3×0+7×2 14 = 3
15=3×5+7×0 15 = 3
数据范围与提示
对于30%的数据:1≤a,b≤50
对于60%的数据: 1≤a,b≤10,000
对于100%的数据:1≤a,b≤1,000,000,000
代码实现:
#include<iostream>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
typedef long long ll;
ll a,b;
inline ll read() {
ll n=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
return n*f;
}
int main() {
a=read(),b=read();
cout<<a*b-a-b<<endl;
}
时间复杂度
题目描述
小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正确。
A++语言的循环结构如下:
F i x y
循环体
E
其中F i x y表示新建变量i(变量i不可与未被销毁的变量重名)并初始化为x, 然后判断i和y的大小关系,若i小于等于y则进入循环,否则不进入。每次循环结束后i都会被修改成i+1,一旦i大于y终止循环。
x和y可以是正整数(x和y的大小关系不定)或变量n是一个表示数据规模的变量,在时间复杂度计算中需保留该变量而不能将其视为常数,该数远大于100。
“E”表示循环体结束。循环体结束时,这个循环体新建的变量也被销毁。
注:本题中为了书写方便,在描述复杂度时,使用大写英文字母“O”表示通常意义下“Θ”的概念。
输入格式:
输入文件第一行一个正整数t,表示有t(t≤10)个程序需要计算时间复杂度。 每个程序我们只需抽取其中 F i x y和E即可计算时间复杂度。
注意:循环结构 允许嵌套。
接下来每个程序的第一行包含一个正整数L和一个字符串,
L代表程序行数,字符串表示这个程序的复杂度,O(1)表示常数复杂度,O(nw)表示复杂度为nw,其 中w是一个小于100的正整数(输入中不包含引号),输入保证复杂度只有O(1)和O(n^w) 两种类型。
接下来L行代表程序中循环结构中的F i x y或者E。程序行若以F开头,表示进入一个循环,之后有空格分离的三个字符(串)i x y, 其中i是一个小写字母(保证不为n),表示新建的变量名,x和y 可能是正整数或n ,已知若为正整数则一定小于100。
程序行若以E开头,则表示循环体结束。
输出格式:
输出文件共t行,对应输入的t个程序,每行输出Yes或No或者ERR(输出中不包含引号),若程序实际复杂度与输入给出的复杂度一致则输出Yes,不一致则输出No,若程序有语法错误(其中语法错误只有: ① F和 E不匹配 ②新建的变量与已经存在但未被销毁的变量重复两种情况),则输出ERR 。
注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出 ERR。
输入样例1: 复制
8
2 O(1)
F i 1 1
E
2 O(n^1)
F x 1 n
E
1 O(1)
F x 1 n
4 O(n^2)
F x 5 n
F y 10 n
E
E
4 O(n^2)
F x 9 n
E
F y 2 n
E
4 O(n^1)
F x 9 n
F y n 4
E
E
4 O(1)
F y n 4
F x 9 n
E
E
4 O(n^2)
F x 1 n
F x 1 10
E
E
输出样例1: 复制
Yes
Yes
ERR
Yes
No
Yes
Yes
ERR
【输入输出样例解释1】
第一个程序i从1到1是常数复杂度。
第二个程序x从1到n是n的一次方的复杂度。
第三个程序有一个F开启循环却没有 E 结束,语法错误。
第四个程序二重循环,n的平方的复杂度。
第五个程序两个一重循环,n的一次方的复杂度。
第六个程序第一重循环正常,但第二重循环开始即终止(因为n远大于100,100大于4)。
第七个程序第一重循环无法进入,故为常数复杂度。
第八个程序第二重循环中的变量x 与第一重循环中的变量重复,出现语法错误②,输出 ERR。
【数据规模与约定】
对于30%的数据:不存在语法错误,数据保证小明给出的每个程序的前 L/2行一定为以 F 开头的语句,第L/2+1行至第L行一定为以E开头的语句,L≤10,若x、y均为整数,x一定小于y,且只有y 有可能为n。
对于50%的数据:不存在语法错误,L≤100,且若x,y均为整数,x一定小于y,且只有y有可能为n。
对于70%的数据:不存在语法错误,L≤100。
对于100%的数据:L≤100。
代码实现:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e4+10;
int f[201],sz[N];
int t,s,w,js,d,res,jc,jz;
int a,b,c,z,y,bz,v,u,q,p,m;
char S1[101],S2[1001];
inline int read() {
int n=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
return n*f;
}
inline void init() {
s=0,w=0,js=0,d=0;
scanf("%d %s\n",&d,S1+1);
int l1=strlen(S1+1);
bz=0;
for(int i=1;i<=l1;++i) {
if(S1[i]=='n') bz=1;
if(S1[i]>='0' && S1[i]<='9') js=js*10+S1[i]-'0';
}
res=0,jc=0,jz=0,a=0,v=0,u=0;
memset(sz,-1,sizeof(sz));
memset(f,0,sizeof(f));
}
inline void work() {
if(u==0) {
if(jc!=jz) printf("ERR\n");
else {
if(bz==0) {
if(res==0) printf("Yes\n");
else printf("No\n");
} else if(bz==1) {
if(res==js) printf("Yes\n");
else printf("No\n");
}
}
}
}
int main() {
t=read();
while(t--) {
init();
while(d--) {
q=0,p=0,m=0;
gets(S2+1);
int l2=strlen(S2+1);
for(int i=1; i<=l2;++i) {
if(S2[i]>='0' && S2[i]<='9') {
if(m==1) v=1;
q=1;
}
if(S2[i]=='n') {
m=1;
if(q==1) p=1;
}
}
b=0,c=0,z=0,y=l2+1;
for(int i=1;i<=l2;i++) {
if(S2[i]>='0' && S2[i]<='9') c=c*10+S2[i]-'0';
if(S2[i]==' ')
if(c!=0) { y=i+1; break; }
}
for(int i=y;i<=l2;i++)
if(S2[i]>='0' && S2[i]<='9') z=z*10+S2[i]-'0';
if(z!=0)
if(c>z) v=1;
f[sz[s]]=0;
for(int i=1;i<=l2;i++) {
if(S2[i]>='a' && S2[i]<='z') {
w++,sz[w]=S2[i],f[S2[i]]++;
if(f[S2[i]]>1 && u==0) printf("ERR\n"),u=1;
break;
}
}
for(int i=1;i<=l2;i++) {
if(S2[i]=='F') {
jc++;
if(p==1) {
a++;
if(v==0) res=max(res,a);
}
}
if(S2[i]=='E') {
jz++;
if(a>0) {
a--;
if(a==0) v=0;
}
f[sz[w]]--,w--;
}
}
}
work();
}
return 0;
}
逛公园
题目描述
策策同学特别喜欢逛公园。公园可以看成一张N个点M条边构成的有向图,且没有 自环和重边。其中1号点是公园的入口,N号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间。策策每天都会去逛公园,他总是从1号点进去,从N号点出来。
策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间。如果1号点 到N号点的最短路长为d,那么策策只会喜欢长度不超过d+K的路线。
策策同学想知道总共有多少条满足条件的路线,你能帮帮它吗?为避免输出过大,答案对P取模。如果有无穷多条合法的路线,请输出−1。
输入输出格式
输入格式:
第一行包含一个整数 TT, 代表数据组数。
接下来TT组数据,对于每组数据: 第一行包含四个整数 N,M,K,P,每两个整数之间用一个空格隔开。
接下来M行,每行三个整数a_i,b_i,c_i,代表编号为a_i,b_i的点之间有一条权值为 c_i的有向边,每两个整数之间用一个空格隔开。
输出格式:
输出文件包含T行,每行一个整数代表答案。
输入样例1: 复制
2
5 7 2 10
1 2 1
2 4 0
4 5 2
2 3 2
3 4 1
3 5 2
1 5 3
2 2 0 10
1 2 0
2 1 0
输出样例1: 复制
3
-1
【样例解释1】
对于第一组数据,最短路为3。 $1 – 5, 1 – 2 – 4 – 5, 1 – 2 – 3 – 5$ 为 3 条合法路径。
【测试数据与约定】
对于不同的测试点,我们约定各种参数的规模不会超过如下
测试点编号 | T | N | M | K | 是否有0边 |
---|---|---|---|---|---|
1 | 5 | 5 | 10 | 0 | 否 |
2 | 5 | 1000 | 2000 | 0 | 否 |
3 | 5 | 1000 | 2000 | 50 | 否 |
4 | 5 | 1000 | 2000 | 50 | 否 |
5 | 5 | 1000 | 2000 | 50 | 否 |
6 | 5 | 1000 | 2000 | 50 | 是 |
7 | 5 | 100000 | 200000 | 0 | 否 |
8 | 3 | 100000 | 200000 | 50 | 否 |
9 | 3 | 100000 | 200000 | 50 | 是 |
10 | 3 | 100000 | 200000 | 50 | 是 |
对于 100%的数据, 1≤P≤10^9,1≤ai,bi≤N , 1≤ci≤1000.
数据保证:至少存在一条合法的路线。
代码实现:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10;
const int M=1e5*2+10;
const int inf=0x3f;
int T,n,m,k,p,js,bz,ans,mod;
int head[M],dis[N],vis[N],f[M][60],a[M][60];
struct node {
int nxt,u,v,val;
}e[M];
inline int read() {
int n=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
return n*f;
}
inline void add_edge(int u,int v,int w) {
e[++js].v=v,e[js].u=u,e[js].val=w;
e[js].nxt=head[u],head[u]=js;
}
inline void spfa() {
queue<int > q;
memset(vis,0,sizeof(vis));
memset(dis,inf,sizeof(dis));
dis[1]=0;
q.push(1);
while (!q.empty()) {
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(dis[v]>dis[u]+e[i].val) {
dis[v]=dis[u]+e[i].val;
if(!vis[v]) {
vis[v]=1;
q.push(v);
}
}
}
}
}
int dfs(int u,int z) {
if(a[u][z]==1 || bz==1) return bz=1;
if(a[u][z]==2) return f[u][z];
a[u][z]=1;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v,res=z+dis[u]-dis[v]-e[i].val;
if(res>k || res<0) continue ;
f[u][z]+=dfs(v,res),f[u][z]%=mod;
}
a[u][z]=2;
return f[u][z];
}
int main() {
T=read();
while (T--) {
int u,v,val;
memset(head,0,sizeof(head));
memset(f,0,sizeof(f));
memset(a,0,sizeof(a));
js=0;
n=read(),m=read(),k=read(),mod=read();
for(int i=1;i<=m;++i) {
u=read(),v=read(),val=read();
add_edge(u,v,val);
}
spfa();
memset(head,0,sizeof(head));
for(int i=1;i<=m;++i) {
swap(e[i].v,e[i].u);
e[i].nxt=head[e[i].u];
head[e[i].u]=i;
}
bz=0,f[1][0]=1,ans=0;
for(int i=0;i<=k;++i) {
ans+=dfs(n,i),ans%=mod;
if(bz==1){
ans=-1;
break;
}
}
printf("%d\n",ans);
}
return 0;
}
奶酪
题目描述
现有一块大奶酪,它的高度为h,它的长度和宽度我们可以认为是无限大的,奶酪 中间有许多 半径相同的球形空洞。我们可以在这块奶酪中建立空间坐标系,在坐标系中, 奶酪的下表面为z=0,奶酪的上表面为z=h。
现在,奶酪的下表面有一只小老鼠Jerry,它知道奶酪中所有空洞的球心所在的坐 标。如果两个空洞相切或是相交,则 Jerry可以从其中一个空洞跑到另一个空洞,特别地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。位于奶酪下表面的 Jerry 想知道,在不破坏奶酪的情况下,能否利用已有的空洞跑到奶酪的上表面去?
空间内两点P_1(x_1,y_1,z_1)、P2(x_2,y_2,z_2)的距离公式如下:
\mathrm{dist}(P_1,P_2)=\sqrt{(x_1-x_2)2+(y_1-y_2)2+(z_1-z_2)^2}
输入格式:
每个输入文件包含多组数据。
第一行,包含一个正整数T,代表该输入文件中所含的数据组数。
接下来是T组数据,每组数据的格式如下: 第一行包含三个正整数n,h和r,两个数之间以一个空格分开,分别代表奶酪中空洞的数量,奶酪的高度和空洞的半径。
接下来的n行,每行包含三个整数x,y,z,两个数之间以一个空格分开,表示空 洞球心坐标为(x,y,z)。
输出格式:
T行,分别对应T组数据的答案,如果在第i组数据中,Jerry 能从下 表面跑到上表面,则输出Yes,如果不能,则输出No (均不包含引号)。
输入样例#1: 复制
3
2 4 1
0 0 1
0 0 3
2 5 1
0 0 1
0 0 4
2 5 2
0 0 2
2 0 4
输出样例#1: 复制
Yes
No
Yes
【输入输出样例 1 说明】
第一组数据,由奶酪的剖面图可见:
第一个空洞在(0,0,0)与下表面相切
第二个空洞在(0,0,4)与上表面相切 两个空洞在(0,0,2)相切输出 Yes
第二组数据,由奶酪的剖面图可见:
两个空洞既不相交也不相切输出 No
第三组数据,由奶酪的剖面图可见:
两个空洞相交 且与上下表面相切或相交输出 Yes
【数据规模与约定】
对于20%的数据,n=1,1≤h,r≤10,000,坐标的绝对值不超过 10,000。
对于40%的数据,1≤n≤8,1≤h,r≤10,000,坐标的绝对值不超过10,000。
对于80%的数据,1≤n≤1,000,1≤h,r≤10,000,坐标的绝对值不超过10,000。
对于 100%100%的数据,1≤n≤1,000,1≤h,r≤1,000,000,000,T≤20,坐标的绝对值不超过1,000,000,000。
代码实现:
#include<iostream>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e3+10;
typedef double dou;
typedef long long ll;
int bz=0,n,T;
int vis[N];
dou h,r;
inline int read() {
int n=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
return n*f;
}
struct node {
dou x,y,z;
bool operator < (const node &a) const {
return z<a.z;
}
}e[N];
inline dou calc(dou a,dou b,dou c,dou A,dou B,dou C) {
return sqrt((A-a)*(A-a)+(B-b)*(B-b)+(C-c)*(C-c));
}
inline void dfs(node w,int jc) {
if(w.z+r>=h) {
bz=1;
return ;
}
vis[jc]=1;
for(int i=1;i<=n;++i) {
if(bz) return;
if(!vis[i] && calc(w.x,w.y,w.z,e[i].x,e[i].y,e[i].z)<=r*2) dfs(e[i],i);
}
}
int main() {
T=read();
while (T--) {
memset(vis,0,sizeof(vis));
memset(e,0,sizeof(e));
bz=0;
scanf("%d%lf%lf",&n,&h,&r);
for(int i=1;i<=n;++i) scanf("%lf%lf%lf",&e[i].x,&e[i].y,&e[i].z);
sort(e+1,e+n+1);
for(int i=1;i<=n;++i)
if(e[i].z-r<=0) dfs(e[i],i);
if(bz) printf("Yes\n");
else printf("No\n");
}
return 0;
}
宝藏(50fen)
题目描述
参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了n个深埋在地下的宝藏屋,也给出了这n个宝藏屋之间可供开发的m 条道路和它们的长度。
小明决心亲自前往挖掘所有宝藏屋中的宝藏。但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路 则相对容易很多。小明的决心感动了考古挖掘的赞助商,赞助商决定免费赞助他打通一条从地面到某个宝藏屋的通道,通往哪个宝藏屋则由小明来决定。
在此基础上,小明还需要考虑如何开凿宝藏屋之间的道路。已经开凿出的道路可以 任意通行不消耗代价。每开凿出一条新道路,小明就会与考古队一起挖掘出由该条道路 所能到达的宝藏屋的宝藏。另外,小明不想开发无用道路,即两个已经被挖掘过的宝藏 屋之间的道路无需再开发。
新开发一条道路的代价是: L×K
L代表这条道路的长度,K代表从赞助商帮你打通的宝藏屋到这条道路起点的宝藏屋所经过的 宝藏屋的数量(包括赞助商帮你打通的宝藏屋和这条道路起点的宝藏屋) 。
请你编写程序为小明选定由赞助商打通的宝藏屋和之后开凿的道路,使得工程总代价最小,并输出这个最小值。
输入格式:
第一行两个用空格分离的正整数n,m,代表宝藏屋的个数和道路数。
接下来m行,每行三个用空格分离的正整数,分别是由一条道路连接的两个宝藏 屋的编号(编号为1-n),和这条道路的长度v。
输出格式:
一个正整数,表示最小的总代价。
输入样例#1: 复制
4 5
1 2 1
1 3 3
1 4 1
2 3 4
3 4 1
输出样例#1: 复制
4
输入样例#2: 复制
4 5
1 2 1
1 3 3
1 4 1
2 3 4
3 4 2
输出样例#2: 复制
5
【样例解释1】
小明选定让赞助商打通了1号宝藏屋。小明开发了道路1→2,挖掘了2号宝 藏。开发了道路1→4,挖掘了4号宝藏。还开发了道路 4→3,挖掘了3号宝 藏。工程总代价为:1×1+1×1+1×2=4
【样例解释2】
小明选定让赞助商打通了1号宝藏屋。小明开发了道路1→2,挖掘了2号宝 藏。开发了道路 1→3,挖掘了3号宝藏。还开发了道路 1→4,挖掘了4号宝 藏。工程总代价为:1×1+3×1+1×1=5
【数据规模与约定】
对于20%的数据: 保证输入是一棵树,1≤n≤8,v≤5000 且所有的v都相等。
对于40%的数据:1≤n≤8,0≤m≤1000,v≤5000 且所有的v都相等。
对于 70%70%的数据:1≤n≤8,0≤m≤1000,v≤5000
对于 100%100%的数据:1≤n≤12,0≤m≤1000,v≤500000
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#define inf 2147483647
using namespace std;
const int N=1e3+10;
const int M=50;
int n,m,u,v,val;
int f[M][M],w[M],vis[M];
struct node {
int u, v;
}e,e2,past[N];
bool operator < (struct node a, struct node b) {
return w[a.u]*f[a.u][a.v]>w[b.u]*f[b.u][b.v];
}
inline int read() {
int n=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
return n*f;
}
inline int dfs(int s) {
memset(w,0,sizeof(w));
memset(vis,0,sizeof(vis));
queue <struct node> q;
int p=0,ans=0;
w[s]=1,vis[s]=1;
for(int i=1;i<=n;++i) {
if(f[s][i]<inf) {
e.u=s,e.v=i;
q.push(e);
}
}
for(int i=1;i<n;++i) {
e=q.front();
q.pop();
while (!q.empty() && ((vis[e.v] || rand()%(n)<1))) {
if(!vis[e.v]) past[p++]=e;
e=q.front();
q.pop();
}
vis[e.v]=1,w[e.v]=w[e.u]+1;
if(p-->0)
for(;p>=0;--p) q.push(past[p]);
p=0;
for(int i=1;i<=n;++i) {
if(f[e.v][i]<inf && !vis[i]) {
e2.u=e.v,e2.v=i;
q.push(e2);
}
}
ans+=f[e.u][e.v]*w[e.u];
}
return ans;
}
int main() {
n=read(),m=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) f[i][j]=inf;
for (int i=0;i<m;++i) {
u=read(),v=read(),val=read();
f[u][v]=f[v][u]=min(val,f[u][v]);
}
srand(201208);
int res=inf;
for(int j=1;j<500;++j)
for (int i=1;i<=n;++i) res=min(res,dfs(i));
printf("%d\n",res);
return 0;
}
列队(QAQ不会,以后再研究吧)
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e3+10;
const int M=5e6+10;
ll n,m,q,x,y,u,t,k,jc,val;
ll f[N][N],rt[M],js[M];
struct node {
ll lc,rc,sum,val;
}e[M<<2];
inline ll read() {
ll n=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while (ch<='9' && ch>='0') {n=(n<<3)+(n<<1)+ch-'0';ch=getchar();}
return n*f;
}
inline void baoli(ll n,ll m,ll q) {
for(ll i=1;i<=n;++i)
for(ll j=1;j<=m;++j) f[i][j]=(i-1)*m+j;
while (q--) {
x=read(),y=read();
ll u=f[x][y];
for(ll i=y;i<m;++i) f[x][i]=f[x][i+1];
for(ll i=x;i<n;++i) f[i][m]=f[i+1][m];
f[n][m]=u;
printf("%d\n",u);
}
}
inline ll get_(ll l,ll r) {
if(k==n+1) {
if(r<=n) return r-l+1;
if(l<=n) return n-l+1;
return 0;
}
if(r<m) return r-l+1;
if(l<m) return m-l ;
return 0;
}
inline ll query(ll &t,ll x,ll l,ll r) {
if(!t) {
t=++jc;
e[t].sum=get_(l,r);
if(l==r) {
if(k<=n) e[t].val=(ll)(k-1)*m+l;
else e[t].val=(ll)l*m;
}
}
e[t].sum--;
if(l==r) return e[t].val;
ll mid=(l+r)>>1;
if((!e[t].lc && x<=(mid-l+1)) || x<=e[e[t].lc].sum) return query(e[t].lc,x,l,mid);
else {
if(!e[t].lc) x-=(mid-l+1);
else x-=e[e[t].lc].sum;
return query(e[t].rc,x,mid+1,r);
}
}
inline void update(ll &t,ll x,ll w,ll l,ll r) {
if(!t) {
t=++jc;
e[t].sum=get_(l,r);
if(l==r) e[t].val=w;
}
e[t].sum++;
if(l==r) return ;
ll mid=(l+r)>>1;
if(x<=mid) update(e[t].lc,x,w,l,mid);
else update(e[t].rc,x,w,mid+1,r);
}
inline ll work(ll n,ll m,ll q) {
ll p=max(m,n)+q;
for(ll i=1;i<=q;++i) {
cin>>x>>y;
if(y==m) k=n+1,val=query(rt[k],x,1,p);
else k=x,val=query(rt[k],y,1,p);
printf("%lld\n",val);
k=n+1;
update(rt[n+1],n+(++js[n+1]),val,1,p);
if(y!=m) {
k=n+1,val=query(rt[k],x,1,p);
k=x,update(rt[x],m-1+(++js[x]),val,1,p);
}
}
return 0;
}
int main() {
n=read(),m=read(),q=read();
if(n<=1000 && m<=1000) baoli(n,m,q);
else work(n,m,q);
return 0;
}
Noip 2017 题目整理的更多相关文章
- Noip往年题目整理
Noip往年题目整理 张炳琪 一.历年题目 按时间倒序排序 年份 T1知识点 T2知识点 T3知识点 得分 总体 2016day1 模拟 Lca,树上差分 期望dp 144 挺难的一套题目,偏思维难度 ...
- NOIp初赛题目整理
NOIp初赛题目整理 这个 blog 用来整理扶苏准备第一轮 csp 时所做的与 csp 没 有 关 系 的历年 noip-J/S 初赛题目,记录了一些我从不知道的细碎知识点,还有一些憨憨题目,不定期 ...
- NOIP 2017 列队 - Splay - 树状数组
题目传送门 传送点I 传送点II 题目大意 (家喻户晓的题目应该不需要大意) (我之前咋把NOIP 2017打成了NOIP 2018,好绝望) Solution 1 Splay 每行一颗Splay,没 ...
- 【游记】NOIP 2017
时间:2017.11.11~2017.11.12 地点:广东省广州市第六中学 Day1 T1:看到题目,心想这种题目也能放在T1? 这个结论我之前遇到过至少3次,自己也简单证明过.初见是NOIP200 ...
- 「NOIP 2017」列队
题目大意:给定一个 $n times m$ 的方阵,初始时第 $i$ 行第 $j$ 列的人的编号为 $(i-1) times m + j$,$q$ 次给出 $x,y$,让第 $x$ 行 $y$ 列的人 ...
- 洛谷 P3951 NOIP 2017 小凯的疑惑
洛谷 P3951 NOIP 2017 小凯的疑惑 题目描述 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有 无数个.在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付 ...
- NOIP 2017 解题报告
---恢复内容开始--- NOIP 2017 的题真的很难啊,怪不得当年我这个萌新爆零了(当然现在也是萌新)越学越觉得自己什么都不会. 想要成为强者要把这些好题都弄懂弄透 至少现在6道题我都比较陌生 ...
- 【数学】NOIP数论内容整理
NOIP数论内容整理 注:特别感谢sdsy的zxy神仙以及lcez的tsr筮安帮助审稿 一.整除: 对于\(a,b~\in~Z\),若\(\exists~k~\in~Z\),\(s.t.~b~=~k~ ...
- Unite 2017 干货整理 优化篇
Unite 2017 干货整理 优化篇 2017年05月16日 将Unite 2017的一些演讲做了整理. 本篇有内存,CPU.GC.UI.渲染性能指标.Tips几个小节. 内容持续整理中. 内存 ...
随机推荐
- 关于.Net使用企业库访问MySql数据库
关于.Net使用企业库访问MySql数据库 在网上看了很多又重写又加WebConfig中的内容,其实不用那么麻烦 企业库5.0访问MySql数据库只需要在Web服务器安装mysql-connector ...
- jQuery.Form.js使用方法
一.jQuery.Form.js 插件的作用是实现Ajax提交表单. 方法: 1.formSerilize() 用于序列化表单中的数据,并将其自动整理成适合AJAX异步请求的URL地址格式. 2.cl ...
- docker swarm yaml
https://www.cnblogs.com/bigberg/p/8867326.html 一.简介 Docker有个编排工具docker-compose,可以将组成某个应该的多个docker容器编 ...
- oracle 逻辑对象
视图 视图的作用: a 让查询返回的字段更容易理解. b 对复杂select语句的封装. c 安全性.视图可以单独授权.对于数据量巨大的表,可以创建视图仅仅返回前100条数据,将该视图select权限 ...
- Date类的相关方法记录
1.Date类中的时间单位是毫秒,System.currentTimeMills()方法就是获取当前时间到1970年1月1日0时0分0秒(西方时间)的毫秒数. public class Test6 { ...
- k8s--yml文件3
- Java知识回顾 (18)Java 8、9、11的新特性
Java 8 Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本. Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 Jav ...
- 知识扩展——(转)一篇文章彻底弄懂Base64编码原理
在互联网中的每一刻,你可能都在享受着Base64带来的便捷,但对于Base64的基础原理又了解多少?今天这篇博文带领大家了解一下Base64的底层实现. 一.Base64的由来 目前Base64已经成 ...
- 如何在SAP Cloud Platform上进行第一个integration flow开发
登录SAP Cloud Platform integration tenant,点击Edit图标: 创建一个新的Content package: 保存content package后,点击artifa ...
- Docker搭建私用仓库
搭建私有仓库 # 1.查找registry,官方的私用仓库镜像 docker search registry # 2.下载私有仓库镜像 docker pull registry # 3.创建并后台运行 ...