T1 入阵曲
不算很水,看题解后明白不叫水题。
为什么你想不到正解,这需要你好好想想。
$n^4$暴力很好想,傻逼二维前缀和完事儿了。然后就是优化了。
怎么优化?题目的数据范围显然是$n^3$的复杂度,朝着这个方向想,考虑我们可以删掉哪一维呢?
首先,我们必须要卡出来一段区间,没有固定区间怎么都不行,在有,$++ans$是肯定不行的,我们一定要找出来规律。
这道题有一个性质,两个数模k相同,那他们相减一定是k的倍数。根据这个性质,我们维护一个桶,记录当前区间总共有模k意义下这个数有多少个,枚举每一列,他们的方案数就是他们可以组成的相同余数的对数,转移即可。
注意一下,当$x%k==0$时,本身已经和k整除,特判一下,注意$++$顺序。
小弟不才。
1 #include<cstdio> 2 #define LL long long 3 #define HZOI std 4 using namespace HZOI; 5 int n,m,k,ooo; 6 int rst[1000003],vis[1000003],tail; 7 LL ans,sm[505][505],t[1000003]; 8 inline int read(); 9 int main() 10 { 11 n=read(),m=read(),k=read(); 12 for (int i=1; i<=n; ++i) 13 for (int j=1; j<=m; ++j) 14 sm[i][j]=sm[i-1][j]+sm[i][j-1]-sm[i-1][j-1]+read(); 15 for (int i=1; i<=n; ++i) 16 for (int j=i; j<=n; ++j) 17 { 18 for (int g=1; g<=m; ++g) 19 { 20 ooo=(sm[j][g]-sm[i-1][g]+k)%k; 21 if (!ooo) ans+=(++t[ooo]); 22 else ans+=(t[ooo]++); 23 if (!vis[ooo]) vis[ooo]=1,rst[++tail]=ooo; 24 } 25 while (tail>0) vis[rst[tail]]=0,t[rst[tail--]]=0; 26 } 27 printf("%lld ",ans); 28 } 29 inline int read() 30 { 31 int nn=0; char cc=getchar(); 32 while (cc<'0' or cc>'9') cc=getchar(); 33 while (cc>='0' and cc<='9') nn=(nn<<3)+(nn<<1)+(cc^48),cc=getchar(); 34 return nn; 35 }
T2 将军令
牛逼题,联赛难度,可是我不会做。
又是贪心题,从儿子开始找,找离他最远的一个可以控制他的祖先,给他点亮,$Dfs$一下,这题就没了。
这个证明吧,我要找更高的父亲,他能控制的点只多不少,只要我找到了一个最深的叶子节点,往上回溯,到达的最远的父亲的子树一定全部被控制,然后贪就可以了。
我用的$Dfs$,转移起来很麻烦,也比较难理解,$Bfs$的方法还是$three_D$神仙教给我的。
主要需要维护好几个东西
- 最深的没有被控制的儿子的$depth$ $di$
- 向上回溯第一个不能被控制的距离(为负值)$minn$
- 向下需要控制的距离$maxx$
- 最深儿子$dimax$
其实最主要的还是$di$,其他三个信息的维护,大部分都是该变量的参与,转移过程很麻烦,兄弟祖先的情况需要很多特判。
小弟不才。
1 #include<cstdio> 2 #include<cstdlib> 3 #define HZOI std 4 using namespace HZOI; 5 const int N=1e6+3; 6 int n,m,opt,ans; 7 int tt,first[N],vv[N<<1],nx[N<<1]; 8 int vis[N],di; 9 void Dfs(int ,int ); 10 inline void Add(int ,int ); 11 inline int read(); 12 inline int max(int a,int b) {return a>b?a:b;} 13 inline int min(int a,int b) {return a<b?a:b;} 14 int main() 15 { 16 n=read(),m=read(),opt=read(); 17 for (int i=1,x,y; i<n; ++i) 18 { 19 x=read(),y=read(); 20 Add(x,y); Add(y,x); 21 } 22 Dfs(1,1); 23 printf("%d ",ans); 24 return 0; 25 } 26 void Dfs(int k,int depth) 27 { 28 vis[k]=1; 29 di=max(depth,di); 30 int maxdi=depth; 31 int minn=0x3f3f3f3f,maxx=0; 32 for (int i=first[k]; i; i=nx[i]) 33 { 34 int ver=vv[i]; 35 if (vis[ver]) continue; 36 Dfs(ver,depth+1); 37 maxx=max(di-depth,maxx), 38 minn=min(di-depth,minn); 39 maxdi=max(di,maxdi); 40 } 41 if (maxx+minn<0) {di=depth+minn;return ;} 42 if (k^1 and maxx>=m) {++ans,di=depth-m-1;return ;} 43 if (k==1 and maxx+minn>=0) {++ans;return ;} 44 di=maxdi; 45 } 46 inline void Add(int u,int v) 47 { 48 vv[++tt]=v,nx[tt]=first[u],first[u]=tt; 49 } 50 inline int read() 51 { 52 int nn=0; char cc=getchar(); 53 while (cc<'0' or cc>'9') cc=getchar(); 54 while (cc>='0' and cc<='9') nn=(nn<<3)+(nn<<1)+(cc^48),cc=getchar(); 55 return nn; 56 }