【NOIPシミュレーション】プチデカダンDay 1
49359 ワード
D1T1
質問A:小奇掘削
初眼構想:記憶化検索
しかし、運行が間違っているようで、私もなぜか分かりません.
正解:線形ダイナミックプランニング得られたお金または支払ったお金は現在の能力に比例するため、現在の能力とお金の混合値 を格納する配列を設定することができる.前効性があるので逆さに押すのはなぜか分かりませんが コアコード
D1T2
質問B:チビの数列
初眼の考え方:暴力配列記録プレフィックス和を開き、すべての区間50 pts を列挙する.
暴力の最適化現在値が0であることが判明すると、break 90 pts に直接breakすることができる.まだ1つの桶を開けることができて、具体的なやり方は私もよく分かりませんが、ACができて、走るのは正解よりずっと速いです.暴力の大法は です.
正解:バランスツリーは依然として配列記録接頭辞和を開き、毎回現在の前駆者を取得して最小差を探し、バランスツリーを挿入し、毎回 を初期化することを覚えている.
ACコード
D1T3
奇ちゃんが地球に帰る
初眼構想:図上二分
正解:図上二分
真・D 1唯一本当にできる問題まず最も重要な点は、複数のデータが初期化されたことを覚えています.memsetが終わったと思ってはいけません.そして、あなたが作ったcntがゼロに戻ることを忘れないでください.私はこのように2回 を実行しました.負のループを判断する必要があります.SPFAで反復回数を判断することができます.反復回数がnより大きいと負のループがあることがわかります. 時間を長くすることができます. SPFAでは、中継点が目的地に到達できるかどうかを判断する必要があります.floyedアルゴリズムを使用して、2点間が に接続されているかどうかを記録するためにブール配列を開きます.二はそれぞれ を間違えた.
ACコード
最終得点100+90+0=190、まだまだ頑張らなきゃ
質問A:小奇掘削
【 】
, ( w) , n 。
【 】
2 : 。
1. : a[i], , a[i]*p , k%, p=p*(1-0.01k)
2. : b[i], , b[i]*p , c%, p=p*(1+0.01c)(p )
:
4 n,k,c,w。
n , 2 type,x。
type 1 ,x a[i];
type 2 ,x b[i];
( ), 。
5 50 50 10
1 10
1 20
2 10
2 20
1 30
375.00
30% n<=100
50% n<=1000,k=100
100% n<=100000,0<=k,c,w,a[i],b[i]<=100
10^9
初眼構想:記憶化検索
しかし、運行が間違っているようで、私もなぜか分かりません.
正解:線形ダイナミックプランニング
for(int i=n;i>=1;i--) {
if(s[i][0]==1) f[i-1]=max(f[i],f[i]*(1-0.01*k)+a[i]*w);
else f[i-1]=max(f[i],f[i]*(1+0.01*c)-b[i]*w);
}
D1T2
質問B:チビの数列
【 】
。
【 】
n , m , l,r P, (a[l'] + a[l'+1] + ... + a[r']) mod P 。
l <= l' <= r' <= r。
。
n m, 。
n , a[1]..a[n]。
m , l,r P, 。
,
4 2
8 15 9 9
1 3 10
1 4 17
2
1
20% n<=100,m<=100,p<=200
40% n<=200,m<=1000,p<=500
70% n<=100000,m<=10000,p<=200
100% n<=500000,m<=10000,p<=500,1<=a[i]<=10^9
初眼の考え方:暴力
暴力の最適化
正解:バランスツリー
ACコード
#include
#include
#include
#define SI 500010
#define inf 0x3f3f3f3f
using namespace std;
struct treap {
int l,r,dat,val;
}a[1010];
int n,m,rt,mn,tot,t[SI];
long long s[SI];
inline int New(int val) {
a[++tot].val=val;
a[tot].dat=rand();
return tot;
}
inline void zig(int &p) {//
int q=a[p].l;
a[p].l=a[q].r,a[q].r=p,p=q;
}
inline void zag(int &p) {//
int q=a[p].r;
a[p].r=a[q].l,a[q].l=p,p=q;
}
inline void insert(int &p,int val) {
if(p==0) {
p=New(val);
return;
}
if(val==a[p].val) return;
if(val<a[p].val) {
insert(a[p].l,val);
if(a[p].dat<a[a[p].l].dat) zig(p);
}
else {
insert(a[p].r,val);
if(a[p].dat<a[a[p].r].dat) zag(p);
}
}
inline void Remove(int &p,int val) {
if(p==0) return;
if(val==a[p].val) {
mn=0;
return;
}
if(val<a[p].val) Remove(a[p].l,val);
else {
mn=min(mn,val-a[p].val);
Remove(a[p].r,val);
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
scanf("%d",&t[i]);
s[i]=s[i-1]+t[i];
}
while(m--) {
memset(a,0,sizeof(a));
int l,r,p;
scanf("%d%d%d",&l,&r,&p);
int ans=p;
if(r-l+1>=p) {
printf("0
");
continue;
}
rt=tot=0; insert(rt,0);
for(int j=l;j<=r;j++) {
int tmp=(s[j]-s[l-1])%p;
mn=inf; Remove(rt,tmp);
insert(rt,tmp);
ans=min(ans,mn);
if(!ans) break;
}
printf("%d
",ans);
}
return 0;
}
D1T3
奇ちゃんが地球に帰る
【 】
, , 。
【 】
, 1 n , 。
, , , a b b a 。
:“ 。”
, 。 。
, 。
, 1 T, 。
, 1 n,m, 。
m , i,j t, i j t。 i j 。
T , 。
, , 1 n 。( 0)。
1 n, -1。
1
4 5
1 2 1
1 3 1
2 3 -3
3 1 1
3 4 1
2
【 】
1, 1, 1→2→3→4, 2+(-2)+2=2。
【 】
1,2 , 1
3,4 ,n<=10
5,6 ,-100<=t<=100
100% T<=10,n<=100,m<=n*(n-1),-100000<=t<=100000
初眼構想:図上二分
正解:図上二分
真・D 1唯一本当にできる問題
ACコード
#include
#include
#include
#define inf 0x3f3f3f3f
using namespace std;
struct edge {
int nex,to,w;
}e[10010];
int T,n,m,cnt,ans,head[105],dis[105],Cnt[105];
bool vis[105][105],v[105]; queue<int> q;
inline int read() {
int c=getchar(),x=0,cf=1;
while(c<'0'||c>'9') {
if(c=='-') cf=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*cf;
}
inline void add(int x,int y,int z) {
e[++cnt].to=y,e[cnt].w=z,e[cnt].nex=head[x],head[x]=cnt;
}
inline bool spfa(int s,int d) {
memset(dis,0x3f,sizeof(dis));
memset(v,false,sizeof(v));
memset(Cnt,0,sizeof(Cnt));
dis[s]=0,v[s]=1,Cnt[s]=0;
q.push(s);
while(q.size()) {
int x=q.front(); q.pop(); v[x]=0;
if(Cnt[x]>=n) return true;
for(int i=head[x];i;i=e[i].nex) {
int y=e[i].to,z=e[i].w;
if(dis[y]>dis[x]+z+d&&vis[y][n]) {
dis[y]=dis[x]+z+d;
Cnt[y]=Cnt[x]+1;
if(Cnt[y]>=n) return true;
if(!v[y]) q.push(y),v[y]=1;
}
}
}
if(dis[n]<0||dis[n]==inf) return true;
return false;
}
int main() {
T=read();
while(T--) {
memset(head,0,sizeof(head));
memset(e,0,sizeof(e));
memset(vis,false,sizeof(vis));
n=read(),m=read(); cnt=0;
for(int i=1;i<=m;i++) {
int x,y,z;
x=read(),y=read(),z=read();
add(x,y,z); vis[x][y]=true;
}
for(int i=1;i<=n;i++) vis[i][i]=true;
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(vis[i][k]&&vis[k][j]) vis[i][j]=true;
if(!vis[1][n]) {
printf("-1
");
continue;
}
int l=-100000,r=100000;
ans=-1;
while(l<=r) {
int mid=(l+r)>>1;
if(spfa(1,mid)) l=mid+1;
else r=mid-1,ans=dis[n];
}
printf("%d
",ans);
}
return 0;
}
最終得点100+90+0=190、まだまだ頑張らなきゃ