Day1
T1 水题,快速幂
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
class DREAD{
public:
int Int(){ int x;read(x);return x; }
private:
bool isdigit(char ch){ return ('0'<=ch && ch<='9'); }
void read(int &x){
char ch;bool pos=1;x=0;
while (ch=getchar())
if (isdigit(ch) || ch=='-'){
if (ch=='-') ch=getchar(),pos=0;
break;
}
for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';
if (!pos) x=-x;
}
}READ;
int N,M,K,X;
LL power(LL a,int b){
if (!b) return 1;
if (b==1) return a;
LL tmp=power(a,b/2);
tmp=((tmp%N)*(tmp%N))%N;
if (b%2==0) return tmp; else return (tmp*a)%N;
}
int main(){
N=READ.Int(),M=READ.Int(),K=READ.Int(),X=READ.Int();
LL tmp=power(10,K);
tmp%=N;
cout<<(X+(tmp*(LL)M)%N)%N<<endl;
return 0;
}
T2排序求逆序对,本来考场上已经往这方面想了,但是最后还是没写写了个60分暴力结果挂了,正解代码:
#include<cstdio>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
#define MP make_pair
class DREAD{
public:
int Int(){ int x;read(x);return x; }
private:
bool isdigit(char ch){ return ('0'<=ch && ch<='9'); }
void read(int &x){
char ch;x=0;
while (ch=getchar()) if (isdigit(ch)) break;
for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';
}
}READ;
template <typename Type> class T_SUM_BIT{
/*--BIT->Binary Indexed Tree--*/
public:
static const int SIZE=100000+10;
Type t[SIZE],sum[SIZE];
int real_size;
void Init(int size){ real_size=size; }
void Build(int size){
real_size=size;
for (int i=1; i<=real_size; ++i) t[i]=sum[i]-sum[i-lowbit(i)];
}
void Modify(int idx,int delta){
for (int p=idx; p<=real_size; p+=lowbit(p)) t[p]+=delta;
}
Type Query(int idx){
Type res=0;
for (int p=idx; p; p-=lowbit(p)) res+=t[p];
return res;
}
private:
int lowbit(int idx){ return idx&-idx; }
};
class PROGRAM{
public:
void Open(){ freopen("data.in","r",stdin); }
void Init(){
N=READ.Int();
for (int i=1; i<=N; ++i) a[i].first=READ.Int(),a[i].second=i;
for (int i=1; i<=N; ++i) b[i].first=READ.Int(),b[i].second=i;
}
void Work(){
sort(a+1,a+N+1);sort(b+1,b+N+1);
for (int i=1; i<=N; ++i) rank[b[i].second]=a[i].second;
bit.Init(N);int res=0;
for (int i=N; i>=1; --i){
res+=bit.Query(rank[i]-1);res%=mod;
bit.Modify(rank[i],1);
}
printf("%d\n", res%mod);
}
private:
static const int N_MAX=100000+10,mod=99999997;
int N,rank[N_MAX];PII a[N_MAX],b[N_MAX];
T_SUM_BIT<int> bit;
}PROG;
int main(){
//PROG.Open();
PROG.Init();
PROG.Work();
return 0;
}
T3最大生成树+LCA,考场上没想出来,写的暴力挂掉了,正解代码:
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
#define it(type) vector<type>::iterator
class DREAD{
public:
int Int(){ int x;read(x);return x; }
private:
bool isdigit(char ch){ return '0'<=ch && ch<='9'; }
void read(int &x){
char ch;x=0;
while (ch=getchar()) if (isdigit(ch)) break;
for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';
}
}READ;
struct Tedge{
int a,b,c;
Tedge(){}
Tedge(int _a,int _b,int _c):a(_a),b(_b),c(_c){}
};
bool cmp_edge(const Tedge &a,const Tedge &b){ return a.c>b.c; }
vector<Tedge> edge;
const int N_MAX=10000+10,M_MAX=100000+10,K_MAX=15,inf=~0u>>1;
int N,M;
void Init(){
N=READ.Int();M=READ.Int();
for (int i=1; i<=M; ++i){
int a=READ.Int(),b=READ.Int(),c=READ.Int();
edge.push_back(Tedge(a,b,c));
}
}
int now[N_MAX],pre[M_MAX],son[M_MAX],v[M_MAX],tot=0;bool vis[N_MAX];
inline void add(int a,int b,int c){ pre[++tot]=now[a];now[a]=tot;son[tot]=b;v[tot]=c; }
inline void con(int a,int b,int c){ add(a,b,c);add(b,a,c); }
int fa[N_MAX];
int find(int x){ return x==fa[x]?x:fa[x]=find(fa[x]); }
void Kruscal(){
sort(edge.begin(),edge.end(),cmp_edge);
for (int i=1; i<=N; ++i) fa[i]=i;
int select=0;
for (it(Tedge) i=edge.begin(); i!=edge.end(); ++i){
int x=find(i->a),y=find(i->b);
if (x==y) continue;
fa[x]=y;con(x,y,i->c);
if (++select==N-1) return;
}
}
struct Tmultiple{
int anc,min;
Tmultiple(){}
Tmultiple(int _anc,int _min):anc(_anc),min(_min){}
}mul[N_MAX][K_MAX];
int dep[N_MAX];
void Dfs(int x){
vis[x]=1;
for (int p=now[x]; p; p=pre[p])
if (!vis[son[p]]){
dep[son[p]]=dep[x]+1;
mul[son[p]][0]=Tmultiple(x,v[p]);
for (int i=1; i<K_MAX; ++i){
mul[son[p]][i].anc=mul[mul[son[p]][i-1].anc][i-1].anc;
mul[son[p]][i].min=min(mul[son[p]][i-1].min,mul[mul[son[p]][i-1].anc][i-1].min);
}
Dfs(son[p]);
}
}
int Answer(int a,int b){
if (find(a)!=find(b)) return -1;
int res=inf;
if (dep[a]<dep[b]) swap(a,b);
for (int i=K_MAX-1; i>=0; --i)
if (dep[a]-(1<<i)>=dep[b]){
res=min(res,mul[a][i].min);
a=mul[a][i].anc;
}
for (int i=K_MAX-1; i>=0; --i)
if (mul[a][i].anc!=mul[b][i].anc){
res=min(res,min(mul[a][i].min,mul[b][i].min));
a=mul[a][i].anc;b=mul[b][i].anc;
}
if (a!=b) return res=min(res,min(mul[a][0].min,mul[b][0].min));
return res;
}
void Solve(){
Kruscal();memset(vis,0,sizeof(vis));
for (int i=1; i<=N; ++i)
if (!vis[i]){
dep[i]=0;
Dfs(i);
}
int Q=READ.Int();
for (int i=1; i<=Q; ++i){
int a=READ.Int(),b=READ.Int();
printf("%d\n", Answer(a,b));
}
}
int main(){
Init();
Solve();
return 0;
}
-------------------------------------分割线------------------------------------------
Day1总结:考场上写第二题的时候有点乱,想的时候脑子一团糟,最后写了个60分的暴力,为了写第三题自己生了两组小数据后就没check了,结果昨天测了民间数据后发现暴力挂了,丢了60分,十分不爽。第三题考场上没想出来,也没check,再丢60。。。。。。如果第一天有220,那省一就毫无压力了。Day1的惨痛经历告诉我,不要过分相信自己的感觉,在考场上一定要稳,既然写了部分分,就一定要拿到,如果考完了发现部分分挂了,那还不如用写部分分的时间想正解。
-------------------------------------分割线-------------------------------------------
Day2
T1是USACO2013MAR的原题Poker Hands,考前做过一遍,结果考场上没想起来,70分暴力幸好没挂,正解代码:
#include<cstdio>
using namespace std;
inline bool isdigit(char ch){return ('0'<=ch && ch<='9');}
inline int read(){
char ch;int tmp=0;
while (ch=getchar()) if (isdigit(ch)) break;
for (; isdigit(ch); ch=getchar()) tmp=tmp*10+ch-'0';
return tmp;
}
inline void write(int &ans){
char ch[9];int tot=0;
while (ans) ch[++tot]=ans%10+'0',ans/=10;
for (int i=tot; i>=1; --i) putchar(ch[i]);
puts("");
}
int main(){
int n=read(),ans=0;
for (int i=1,num=0,pre=0; i<=n; ++i,pre=num){
num=read();
if (num>pre) ans+=num-pre;
}
write(ans);
return 0;
}
T2贪心或者线段树优化DP,我考场上写的是贪心,直接O(n)取出每个单调区间的最高点和最低点再求答案
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
#define MP make_pair
class DREAD{
public:
int Int(){ int x;read(x);return x; }
private:
bool isdigit(char ch){ return ('0'<=ch && ch<='9'); }
void read(int &x){
char ch;bool pos=1;x=0;
while (ch=getchar())
if (ch=='-' || isdigit(ch)){
if (ch=='-') ch=getchar(),pos=0;
break;
}
for (; isdigit(ch); ch=getchar()) x=x*10+ch-'0';
if (!pos) x=-x;
}
}READ;
const int N_MAX=100000+10;
int N,a[N_MAX];
struct Tseg{
int first,second,flag;
Tseg(){}
Tseg(int _first,int _second,int _flag):first(_first),second(_second),flag(_flag){}
};
vector<Tseg> vec;
enum Ttype{DEC,INC};
int DOA(){
int res=1;
if (vec[0].flag==DEC) res+=vec.size()-1;
else res+=vec.size();
return res;
}
int DOB(){
int res=1;
if (vec[0].flag==INC) res+=vec.size()-1;
else res+=vec.size();
return res;
}
int main(){
N=READ.Int();
if (N==1){ puts("1");return 0; }
if (!N){ puts("0");return 0; }
for (int i=1; i<=N; ++i) a[i]=READ.Int();
int BP;
for (int i=1; i<=N; ++i) if (a[i]!=a[i+1]){
BP=i;
break;
}
int flag=(a[BP+1]>a[BP]),L=1,R;
for (int i=BP+2; i<=N; ++i){
if (flag){
if (a[i]<a[i-1]){
flag=DEC;
vec.push_back(Tseg(L,i-1,INC));
L=i-1;
}
}
else{
if (a[i]>a[i-1]){
flag=INC;
vec.push_back(Tseg(L,i-1,DEC));
L=i-1;
}
}
}
if (L!=N) vec.push_back(Tseg(L,N,flag));
int res1=DOA(),res2=DOB();
printf("%d\n", res1>res2?res1:res2);
return 0;
}
T3对正解不明觉厉,直接乱搞,不知道多少分。。。
-------------------------------------分割线-----------------------------------------
Day2总结:Day2比Day1考的要好一些,虽然第一题没想到正解,但至少拿了70分暴力
-------------------------------------分割线-----------------------------------------
这次NOIP总体来说是挂了,原本预计400结果只有270,一等是没希望了,只有吸取这次的教训,为以后的比赛积累经验。考场上要尽量保持KISS原则,结果D1T2的暴力却写的十分冗长。总的来说考场上还是应该以得分为主。另外就当是为今年的省选攒RP吧。。。